summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt53
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt60
-rw-r--r--Documentation/devicetree/bindings/regulator/gdsc-regulator.txt6
-rwxr-xr-xDocumentation/devicetree/bindings/sound/qcom-audio-dev.txt5
-rw-r--r--Documentation/devicetree/bindings/sound/wcd_codec.txt17
-rw-r--r--Documentation/devicetree/bindings/usb/msm-ssusb.txt1
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt1
-rw-r--r--arch/arm/boot/dts/qcom/dsi-panel-jdi-1080p-video.dtsi66
-rw-r--r--arch/arm/boot/dts/qcom/msm-arm-smmu-impl-defs-cobalt.dtsi564
-rw-r--r--arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/msm8996.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-cdp.dtsi17
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-mtp.dtsi17
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi6
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi17
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-mdss-panels.dtsi14
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi8
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi17
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi19
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-pm.dtsi495
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi7
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt.dtsi10
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon.dtsi10
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig6
-rw-r--r--arch/arm64/configs/msmcortex_defconfig6
-rw-r--r--drivers/bluetooth/btfm_slim.c3
-rw-r--r--drivers/bluetooth/btfm_slim.h2
-rw-r--r--drivers/bluetooth/btfm_slim_codec.c22
-rw-r--r--drivers/bluetooth/btfm_slim_wcn3990.c2
-rw-r--r--drivers/clk/msm/Makefile1
-rw-r--r--drivers/clk/msm/clock-gcc-8996.c27
-rw-r--r--drivers/clk/msm/clock-mmss-8996.c17
-rw-r--r--drivers/clk/msm/gdsc.c46
-rw-r--r--drivers/clk/msm/reset.c94
-rw-r--r--drivers/clk/msm/reset.h39
-rw-r--r--drivers/cpuidle/lpm-levels.c4
-rw-r--r--drivers/crypto/msm/ice.c7
-rw-r--r--drivers/crypto/msm/iceregs.h11
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.c4
-rw-r--r--drivers/input/touchscreen/Kconfig11
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/ft5x06_ts.c777
-rw-r--r--drivers/input/touchscreen/it7258_ts_i2c.c1234
-rw-r--r--drivers/input/touchscreen/msg21xx_ts.c3272
-rw-r--r--drivers/iommu/arm-smmu.c224
-rw-r--r--drivers/platform/msm/Kconfig11
-rw-r--r--drivers/platform/msm/ipa/Makefile1
-rw-r--r--drivers/platform/msm/ipa/ipa_api.c44
-rw-r--r--drivers/platform/msm/ipa/ipa_common_i.h1
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c6
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_i.h1
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c16
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c5
-rw-r--r--drivers/platform/msm/ipa/test/Makefile2
-rw-r--r--drivers/platform/msm/ipa/test/ipa_test_example.c99
-rw-r--r--drivers/platform/msm/ipa/test/ipa_ut_framework.c969
-rw-r--r--drivers/platform/msm/ipa/test/ipa_ut_framework.h222
-rw-r--r--drivers/platform/msm/ipa/test/ipa_ut_i.h86
-rw-r--r--drivers/platform/msm/ipa/test/ipa_ut_suite_list.h35
-rw-r--r--drivers/power/power_supply_sysfs.c2
-rw-r--r--drivers/power/qcom-charger/fg-core.h1
-rw-r--r--drivers/power/qcom-charger/qpnp-fg-gen3.c6
-rw-r--r--drivers/power/qcom-charger/smb-lib.c60
-rw-r--r--drivers/power/qcom-charger/smb-lib.h6
-rw-r--r--drivers/power/qcom-charger/smb138x-charger.c15
-rw-r--r--drivers/soc/qcom/core_hang_detect.c11
-rw-r--r--drivers/soc/qcom/gladiator_hang_detect.c8
-rw-r--r--drivers/soc/qcom/qdsp6v2/apr_tal_glink.c13
-rw-r--r--drivers/soc/qcom/qsee_ipc_irq_bridge.c10
-rw-r--r--drivers/soc/qcom/service-locator.c18
-rw-r--r--drivers/soc/qcom/service-notifier.c56
-rw-r--r--drivers/usb/dwc3/core.h1
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c79
-rw-r--r--drivers/usb/dwc3/gadget.c21
-rw-r--r--drivers/usb/gadget/function/f_cdev.c5
-rw-r--r--drivers/usb/pd/policy_engine.c11
-rw-r--r--drivers/video/fbdev/msm/mdss.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_debug.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_debug_xlog.c9
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_host.c3
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h3
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_debug.c791
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_hwio.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c40
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_layer.c4
-rw-r--r--drivers/video/fbdev/msm/mdss_smmu.c9
-rw-r--r--include/dt-bindings/clock/msm-clocks-8996.h29
-rw-r--r--include/dt-bindings/clock/qcom,gcc-msmfalcon.h445
-rw-r--r--include/dt-bindings/clock/qcom,gpu-msmfalcon.h40
-rw-r--r--include/dt-bindings/clock/qcom,mmcc-msmfalcon.h367
-rw-r--r--include/linux/input/ft5x06_ts.h24
-rw-r--r--include/linux/power_supply.h2
-rw-r--r--include/sound/apr_audio-v2.h331
-rw-r--r--include/sound/q6afe-v2.h3
-rwxr-xr-xinclude/uapi/linux/mfd/wcd9xxx/Kbuild1
-rw-r--r--[-rwxr-xr-x]include/uapi/linux/mfd/wcd9xxx/wcd9xxx_registers.h (renamed from include/linux/mfd/wcd9xxx/wcd9xxx_registers.h)11
-rw-r--r--kernel/cpu.c15
-rw-r--r--kernel/cpuset.c18
-rw-r--r--net/netlink/genetlink.c2
-rw-r--r--net/wireless/db.txt62
-rwxr-xr-xsound/soc/codecs/Kconfig6
-rw-r--r--sound/soc/codecs/Makefile3
-rw-r--r--sound/soc/codecs/msm8x16/Kconfig3
-rw-r--r--sound/soc/codecs/msm8x16/Makefile3
-rw-r--r--sound/soc/codecs/msm8x16/msm8916-wcd-irq.c (renamed from sound/soc/codecs/msm8916-wcd-irq.c)56
-rw-r--r--sound/soc/codecs/msm8x16/msm8916-wcd-irq.h (renamed from sound/soc/codecs/msm8916-wcd-irq.h)0
-rw-r--r--sound/soc/codecs/msm8x16/msm89xx-regmap.c417
-rw-r--r--sound/soc/codecs/msm8x16/msm8x16-wcd-tables.c263
-rw-r--r--sound/soc/codecs/msm8x16/msm8x16-wcd.c6037
-rw-r--r--sound/soc/codecs/msm8x16/msm8x16-wcd.h341
-rw-r--r--sound/soc/codecs/msm8x16/msm8x16_wcd_registers.h585
-rw-r--r--sound/soc/codecs/wcd9335.c31
-rw-r--r--sound/soc/codecs/wcd9xxx-common-v2.c172
-rw-r--r--sound/soc/codecs/wcd9xxx-common-v2.h10
-rw-r--r--sound/soc/msm/msmcobalt.c46
-rw-r--r--sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c183
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c347
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h1
-rw-r--r--sound/soc/msm/qdsp6v2/q6afe.c171
119 files changed, 16943 insertions, 2991 deletions
diff --git a/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
new file mode 100644
index 000000000000..1c7c2c5ea99f
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
@@ -0,0 +1,53 @@
+FocalTech touch controller
+
+The focaltech controller is connected to host processor
+via i2c. The controller generates interrupts when the
+user touches the panel. The host controller is expected
+to read the touch coordinates over i2c and pass the coordinates
+to the rest of the system.
+
+Required properties:
+
+ - compatible : should be "focaltech,5x06".
+ - reg : i2c slave address of the device.
+ - interrupt-parent : parent of interrupt.
+ - interrupts : touch sample interrupt to indicate presense or release
+ of fingers on the panel.
+ - vdd-supply : Power supply needed to power up the device.
+ - vcc_i2c-supply : Power source required to power up i2c bus.
+ - focaltech,family-id : family identification of the controller.
+ - focaltech,irq-gpio : irq gpio which is to provide interrupts to host,
+ same as "interrupts" node. It will also
+ contain active low or active high information.
+ - focaltech,reset-gpio : reset gpio to control the reset of chip.
+ - focaltech,display-coords : display coordinates in pixels. It is a four
+ tuple consisting of min x, min y, max x and
+ max y values.
+
+Optional properties:
+
+ - focaltech,panel-coords : panel coordinates for the chip in pixels.
+ It is a four tuple consisting of min x,
+ min y, max x and max y values.
+ - focaltech,i2c-pull-up : to specify pull up is required.
+ - focaltech,no-force-update : to specify force update is allowed.
+ - focaltech,button-map : button map of key codes. The number
+ of key codes depend on panel.
+
+Example:
+ i2c@f9924000 {
+ ft5x06_ts@38 {
+ compatible = "focaltech,5x06";
+ reg = <0x38>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <61 0x2>;
+ vdd-supply = <&pm8941_l22>;
+ vcc_i2c-supply = <&pm8941_s3>;
+ focaltech,reset-gpio = <&msmgpio 60 0x00>;
+ focaltech,irq-gpio = <&msmgpio 61 0x00>;
+ focaltech,panel-coords = <0 0 480 800>;
+ focaltech,display-coords = <0 0 480 800>;
+ focaltech,button-map= <158 102 139 217>;
+ focaltech,family-id = <0x0a>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt
new file mode 100644
index 000000000000..26f01ca8577f
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt
@@ -0,0 +1,60 @@
+Mstar touch controller
+
+The mstar controller is connected to host processor
+via i2c. The controller generates interrupts when the
+user touches the panel. The host controller is expected
+to read the touch coordinates over i2c and pass the coordinates
+to the rest of the system.
+
+Required properties:
+
+ - compatible : should be "mstar,msg21xx".
+ - reg : i2c slave address of the device.
+ - interrupt-parent : parent of interrupt.
+ - interrupts : touch sample interrupt to indicate presense or release
+ of fingers on the panel.
+ - vdd-supply : Power supply needed to power up the device.
+ - vcc_i2c-supply : Power source required to power up i2c bus.
+ - mstar,irq-gpio : irq gpio which is to provide interrupts to host,
+ same as "interrupts" node. It will also
+ contain active low or active high information.
+ - mstar,reset-gpio : reset gpio to control the reset of chip.
+ - mstar,display-coords : display coords in pixels. It is a four
+ tuple consisting of min x, min y, max x and
+ max y values.
+ - pinctrl-names : This should be defined if a target uses pinctrl framework.
+ See "pinctrl" in Documentation/devicetree/bindings/pinctrl/msm-pinctrl.txt.
+ Specify the names of the configs that pinctrl can install in driver.
+ Following are the pinctrl configs that can be installed:
+ "pmx_ts_active" : Active configuration of pins, this should specify active
+ config defined in pin groups of interrupt and reset gpio.
+ "pmx_ts_suspend" : Disabled configuration of pins, this should specify sleep
+ config defined in pin groups of interrupt and reset gpio.
+ "pmx_ts_release" : Release configuration of pins, this should specify
+ release config defined in pin groups of interrupt and reset gpio.
+
+Optional properties:
+
+ - mstar,button-map : button map of key codes. It is a three tuple consisting of key codes.
+ - mstar,panel-coords : panel coords for the chip in pixels.
+ It is a four tuple consisting of min x,
+ min y, max x and max y values.
+
+Example:
+ i2c@78b9000 { /* BLSP1 QUP5 */
+ mstar@26 {
+ compatible = "mstar,msg21xx";
+ reg = <0x26>;
+ interrupt-parent = <&msm_gpio>;
+ interrupts = <13 0x2008>;
+ mstar,irq-gpio = <&msm_gpio 13 0x00000001>;
+ mstar,reset-gpio = <&msm_gpio 12 0x0>;
+ vdd-supply = <&pm8916_l17>;
+ vcc_i2c-supply = <&pm8916_l6>;
+ mstar,display-coords = <0 0 480 854>;
+ pinctrl-names = "pmx_ts_active","pmx_ts_suspend";
+ pinctrl-0 = <&ts_int_active &ts_reset_active>;
+ pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+ mstar,button-map= <172 139 158>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
index 526c51836402..20e5c5be37ce 100644
--- a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
@@ -50,6 +50,12 @@ Optional properties:
to enable.
- qcom,reset-aon-logic: If present, the GPU DEMET cells need to be reset while
enabling the GX GDSC.
+ - resets: reset specifier pair consisting of phandle for the reset controller
+ and reset lines used by this controller. These can be
+ supplied only if we support qcom,skip-logic-collapse.
+ - reset-names: reset signal name strings sorted in the same order as the resets
+ property. These can be supplied only if we support
+ qcom,skip-logic-collapse.
Example:
gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 7fa51e394f5c..c8f8d38c2a5e 100755
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -725,6 +725,11 @@ Optional Properties:
Example:
+ msm_dig_codec: qcom,msm-int-codec {
+ compatible = "qcom,msm_int_core_codec";
+ qcom,dig-cdc-base-addr = <0xc0f0000>;
+ };
+
sound {
compatible = "qcom,msm8x16-audio-codec";
qcom,model = "msm8x16-snd-card";
diff --git a/Documentation/devicetree/bindings/sound/wcd_codec.txt b/Documentation/devicetree/bindings/sound/wcd_codec.txt
index e37e7c2bea3c..c0a7a240b922 100644
--- a/Documentation/devicetree/bindings/sound/wcd_codec.txt
+++ b/Documentation/devicetree/bindings/sound/wcd_codec.txt
@@ -383,7 +383,9 @@ i2c@f9925000 {
Tombak audio CODEC in SPMI mode
- - compatible = "qcom,msm8x16_wcd_codec";
+ - compatible = "qcom,msm-codec-core",
+ - compatible = "qcom,pmic-codec-digital"
+ - compatible = "qcom,pmic-codec-analog"
- reg: represents the slave base address provided to the peripheral.
- interrupt-parent : The parent interrupt controller.
- interrupts: List of interrupts in given SPMI peripheral.
@@ -435,8 +437,19 @@ Optional properties:
core register writes.
Example:
+
+msm_dig_codec: qcom,msm-int-codec {
+ compatible = "qcom,msm_int_core_codec";
+ qcom,dig-cdc-base-addr = <0xc0f0000>;
+};
+
+msm8x16_wcd_codec@f100 {
+ compatible = "qcom,msm_int_pmic_analog_codec";
+ reg = <0xf100 0x100>;
+};
+
msm8x16_wcd_codec@f000{
- compatible = "qcom,msm8x16_wcd_codec";
+ compatible = "qcom,msm_int_pmic_digital_codec";
reg = <0xf000 0x100>;
interrupt-parent = <&spmi_bus>;
interrupts = <0x1 0xf0 0x0>,
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index 2b2bfe428c79..c5e5f1851fc2 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -50,6 +50,7 @@ Optional properties :
- qcom,disable-dev-mode-pm: If present, it disables PM runtime functionality for device mode.
- qcom,disable-host-mode-pm: If present, it disables XHCI PM runtime functionality when USB
host mode is used.
+- qcom,core-clk-rate: If present, indicates clock frequency to be set for USB master clock.
- extcon: phandles to external connector devices. First phandle should point to
external connector, which provide "USB" cable events, the second
should point to external connector device, which provide "USB-HOST"
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 4097b7cd6454..aca2dd3e4ccb 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -146,6 +146,7 @@ mosaixtech Mosaix Technologies, Inc.
moxa Moxa
mpl MPL AG
msi Micro-Star International Co. Ltd.
+mstar MStar Semiconductor, Inc.
mti Imagination Technologies Ltd. (formerly MIPS Technologies Inc.)
mundoreader Mundo Reader S.L.
murata Murata Manufacturing Co., Ltd.
diff --git a/arch/arm/boot/dts/qcom/dsi-panel-jdi-1080p-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-jdi-1080p-video.dtsi
new file mode 100644
index 000000000000..cecd8d3cf2a0
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/dsi-panel-jdi-1080p-video.dtsi
@@ -0,0 +1,66 @@
+/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+&mdss_mdp {
+ dsi_jdi_1080_vid: qcom,mdss_dsi_jdi_1080p_video {
+ qcom,mdss-dsi-panel-name = "jdi 1080p video mode dsi panel";
+ qcom,mdss-dsi-panel-type = "dsi_video_mode";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <1080>;
+ qcom,mdss-dsi-panel-height = <1920>;
+ qcom,mdss-dsi-h-front-porch = <96>;
+ qcom,mdss-dsi-h-back-porch = <64>;
+ qcom,mdss-dsi-h-pulse-width = <16>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <16>;
+ qcom,mdss-dsi-v-front-porch = <4>;
+ qcom,mdss-dsi-v-pulse-width = <1>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-on-command = [15 01 00 00 00 00 02 55 00
+ 15 01 00 00 00 00 02 53 2C
+ 15 01 00 00 00 00 02 35 00
+ 05 01 00 00 78 00 02 29 00
+ 05 01 00 00 78 00 02 11 00];
+ qcom,mdss-dsi-off-command = [05 01 00 00 02 00 02 28 00
+ 05 01 00 00 79 00 02 10 00];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-h-sync-pulse = <0>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-lane-2-state;
+ qcom,mdss-dsi-lane-3-state;
+ qcom,mdss-dsi-panel-timings =
+ [e7 36 24 00 66 6a 2a 3a 2d 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x04>;
+ qcom,mdss-dsi-t-clk-pre = <0x1b>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+ qcom,mdss-pan-physical-width-dimension = <61>;
+ qcom,mdss-pan-physical-height-dimension = <110>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msm-arm-smmu-impl-defs-cobalt.dtsi b/arch/arm/boot/dts/qcom/msm-arm-smmu-impl-defs-cobalt.dtsi
new file mode 100644
index 000000000000..feb74b5480f1
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msm-arm-smmu-impl-defs-cobalt.dtsi
@@ -0,0 +1,564 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+
+&kgsl_smmu {
+ attach-impl-defs = <0x6000 0x3270>,
+ <0x6060 0x1055>,
+ <0x6470 0x110011>,
+ <0x6478 0x0>,
+ <0x647c 0x1000100>,
+ <0x6480 0x81108110>,
+ <0x6484 0x81108110>,
+ <0x6488 0x3e003e0>,
+ <0x648c 0x3e003e0>,
+ <0x6490 0x80008010>,
+ <0x6494 0x8020>,
+ <0x649c 0x6>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6924 0x604>,
+ <0x6928 0x11000>,
+ <0x6930 0x800>,
+ <0x6b64 0x1a5551>,
+ <0x6b68 0x2aaa2f82>;
+};
+
+&lpass_q6_smmu {
+ attach-impl-defs = <0x6000 0x3270>,
+ <0x6060 0x1055>,
+ <0x6070 0xe0>,
+ <0x6074 0xe0>,
+ <0x6078 0xe0>,
+ <0x607c 0xe0>,
+ <0x60f0 0xc0>,
+ <0x60f4 0xc8>,
+ <0x60f8 0xd0>,
+ <0x60fc 0xd8>,
+ <0x6170 0x0>,
+ <0x6174 0x30>,
+ <0x6178 0x60>,
+ <0x617c 0x90>,
+ <0x6270 0x0>,
+ <0x6274 0x2>,
+ <0x6278 0x4>,
+ <0x627c 0x6>,
+ <0x62f0 0x8>,
+ <0x62f4 0xe>,
+ <0x62f8 0x14>,
+ <0x62fc 0x1a>,
+ <0x6370 0x20>,
+ <0x6374 0x40>,
+ <0x6378 0x60>,
+ <0x637c 0x80>,
+ <0x67a0 0x0>,
+ <0x67a4 0x0>,
+ <0x67a8 0x20>,
+ <0x67b0 0x0>,
+ <0x67b4 0x8>,
+ <0x67b8 0xc8>,
+ <0x67d0 0x4>,
+ <0x67dc 0x8>,
+ <0x67e0 0x8>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6924 0x202>,
+ <0x6928 0x10a00>,
+ <0x6930 0x500>,
+ <0x6b64 0x121151>,
+ <0x6b68 0x8a840080>,
+ <0x6c00 0x0>,
+ <0x6c04 0x0>,
+ <0x6c08 0x0>,
+ <0x6c0c 0x0>,
+ <0x6c10 0x1>,
+ <0x6c14 0x1>,
+ <0x6c18 0x1>,
+ <0x6c1c 0x1>,
+ <0x6c20 0x2>,
+ <0x6c24 0x2>,
+ <0x6c28 0x2>,
+ <0x6c2c 0x2>,
+ <0x6c30 0x3>,
+ <0x6c34 0x3>,
+ <0x6c38 0x3>,
+ <0x6c3c 0x3>;
+};
+
+&mmss_smmu {
+ attach-impl-defs = <0x6000 0x3270>,
+ <0x6060 0x1055>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6924 0x204>,
+ <0x6928 0x11002>,
+ <0x6930 0x800>,
+ <0x6960 0xffffffff>,
+ <0x6964 0xffffffff>,
+ <0x6968 0xffffffff>,
+ <0x696c 0xffffffff>,
+ <0x6b48 0x330330>,
+ <0x6b4c 0x81>,
+ <0x6b50 0x3333>,
+ <0x6b54 0x3333>,
+ <0x6b64 0x1a5555>,
+ <0x6b68 0x9aaa892a>,
+ <0x6b70 0x10100002>,
+ <0x6b74 0x10100002>,
+ <0x6b78 0x10100002>,
+ <0x6b80 0x20042004>,
+ <0x6b84 0x20042004>;
+};
+
+&anoc1_smmu {
+ attach-impl-defs = <0x6000 0x3270>,
+ <0x6060 0x1055>,
+ <0x6070 0x19>,
+ <0x6074 0x39>,
+ <0x6078 0x41>,
+ <0x607c 0x59>,
+ <0x6080 0x95>,
+ <0x6084 0x98>,
+ <0x6088 0xc0>,
+ <0x608c 0xc0>,
+ <0x60f0 0x0>,
+ <0x60f4 0x2>,
+ <0x60f8 0x5>,
+ <0x60fc 0x8>,
+ <0x6100 0x16>,
+ <0x6104 0x17>,
+ <0x6108 0x19>,
+ <0x610c 0x19>,
+ <0x6170 0x0>,
+ <0x6174 0x0>,
+ <0x6178 0x0>,
+ <0x617c 0x0>,
+ <0x6180 0x0>,
+ <0x6184 0x0>,
+ <0x6188 0x0>,
+ <0x618c 0x0>,
+ <0x6270 0x0>,
+ <0x6274 0xd>,
+ <0x6278 0xe>,
+ <0x627c 0x12>,
+ <0x6280 0x16>,
+ <0x6284 0x16>,
+ <0x6288 0x18>,
+ <0x628c 0x18>,
+ <0x62f0 0x18>,
+ <0x62f4 0x1b>,
+ <0x62f8 0x1c>,
+ <0x62fc 0x24>,
+ <0x6300 0x28>,
+ <0x6304 0x2b>,
+ <0x6308 0x31>,
+ <0x630c 0x31>,
+ <0x6370 0x31>,
+ <0x6374 0x34>,
+ <0x6378 0x35>,
+ <0x637c 0x47>,
+ <0x6380 0x4f>,
+ <0x6384 0x54>,
+ <0x6388 0x60>,
+ <0x638c 0x60>,
+ <0x67a0 0x0>,
+ <0x67a4 0xa7>,
+ <0x67a8 0xc0>,
+ <0x67b0 0x0>,
+ <0x67b4 0x18>,
+ <0x67b8 0x7c>,
+ <0x67d0 0x0>,
+ <0x67dc 0x4>,
+ <0x67e0 0x8>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6b64 0x121151>,
+ <0x6b68 0xbb804080>,
+ <0x6c00 0x0>,
+ <0x6c04 0x0>,
+ <0x6c08 0x0>,
+ <0x6c0c 0x0>,
+ <0x6c10 0x0>,
+ <0x6c14 0x0>,
+ <0x6c18 0x0>,
+ <0x6c1c 0x0>,
+ <0x6c20 0x0>,
+ <0x6c24 0x0>,
+ <0x6c28 0x0>,
+ <0x6c2c 0x0>,
+ <0x6c30 0x0>,
+ <0x6c34 0x0>,
+ <0x6c38 0x0>,
+ <0x6c3c 0x0>,
+ <0x6c40 0x0>,
+ <0x6c44 0x0>,
+ <0x6c48 0x0>,
+ <0x6c4c 0x0>,
+ <0x6c50 0x0>,
+ <0x6c54 0x0>,
+ <0x6c58 0x0>,
+ <0x6c5c 0x0>,
+ <0x6c60 0x0>,
+ <0x6c64 0x0>,
+ <0x6c68 0x0>,
+ <0x6c6c 0x0>,
+ <0x6c70 0x0>,
+ <0x6c74 0x0>,
+ <0x6c78 0x0>,
+ <0x6c7c 0x0>,
+ <0x6c80 0x0>,
+ <0x6c84 0x1>,
+ <0x6c88 0x0>,
+ <0x6c8c 0x0>,
+ <0x6c90 0x4>,
+ <0x6c94 0x3>,
+ <0x6c98 0x2>,
+ <0x6c9c 0x0>,
+ <0x6ca0 0x5>,
+ <0x6ca4 0x5>,
+ <0x6ca8 0x0>,
+ <0x6cac 0x0>,
+ <0x6cb0 0x0>,
+ <0x6cb4 0x0>,
+ <0x6cb8 0x0>,
+ <0x6cbc 0x0>,
+ <0x6cc0 0x0>,
+ <0x6cc4 0x0>,
+ <0x6cc8 0x0>,
+ <0x6ccc 0x0>,
+ <0x6cd0 0x0>,
+ <0x6cd4 0x0>,
+ <0x6cd8 0x0>,
+ <0x6cdc 0x0>,
+ <0x6ce0 0x0>,
+ <0x6ce4 0x0>,
+ <0x6ce8 0x0>,
+ <0x6cec 0x0>,
+ <0x6cf0 0x0>,
+ <0x6cf4 0x0>,
+ <0x6cf8 0x0>,
+ <0x6cfc 0x0>,
+ <0x6d00 0x0>,
+ <0x6d04 0x0>,
+ <0x6d08 0x0>,
+ <0x6d0c 0x0>,
+ <0x6d10 0x0>,
+ <0x6d14 0x0>,
+ <0x6d18 0x0>,
+ <0x6d1c 0x0>,
+ <0x6d20 0x0>,
+ <0x6d24 0x0>,
+ <0x6d28 0x0>,
+ <0x6d2c 0x0>,
+ <0x6d30 0x0>,
+ <0x6d34 0x0>,
+ <0x6d38 0x0>,
+ <0x6d3c 0x0>,
+ <0x6d40 0x0>,
+ <0x6d44 0x0>,
+ <0x6d48 0x0>,
+ <0x6d4c 0x0>,
+ <0x6d50 0x0>,
+ <0x6d54 0x0>,
+ <0x6d58 0x0>,
+ <0x6d5c 0x0>,
+ <0x6d60 0x0>,
+ <0x6d64 0x0>,
+ <0x6d68 0x0>,
+ <0x6d6c 0x0>,
+ <0x6d70 0x0>,
+ <0x6d74 0x0>,
+ <0x6d78 0x0>,
+ <0x6d7c 0x0>,
+ <0x6d80 0x0>,
+ <0x6d84 0x0>,
+ <0x6d88 0x0>,
+ <0x6d8c 0x0>,
+ <0x6d90 0x0>,
+ <0x6d94 0x0>,
+ <0x6d98 0x0>,
+ <0x6d9c 0x0>,
+ <0x6da0 0x0>,
+ <0x6da4 0x0>,
+ <0x6da8 0x0>,
+ <0x6dac 0x0>,
+ <0x6db0 0x0>,
+ <0x6db4 0x0>,
+ <0x6db8 0x0>,
+ <0x6dbc 0x0>,
+ <0x6dc0 0x0>,
+ <0x6dc4 0x0>,
+ <0x6dc8 0x0>,
+ <0x6dcc 0x0>,
+ <0x6dd0 0x0>,
+ <0x6dd4 0x0>,
+ <0x6dd8 0x0>,
+ <0x6ddc 0x0>,
+ <0x6de0 0x0>,
+ <0x6de4 0x0>,
+ <0x6de8 0x0>,
+ <0x6dec 0x0>,
+ <0x6df0 0x0>,
+ <0x6df4 0x0>,
+ <0x6df8 0x0>,
+ <0x6dfc 0x0>;
+};
+
+&anoc2_smmu {
+ attach-impl-defs = <0x6000 0x3270>,
+ <0x6060 0x1055>,
+ <0x6070 0x12>,
+ <0x6074 0x26>,
+ <0x6078 0x3a>,
+ <0x607c 0x3c>,
+ <0x6080 0x3f>,
+ <0x6084 0x67>,
+ <0x6088 0x6c>,
+ <0x608c 0x74>,
+ <0x6090 0x7c>,
+ <0x6094 0x80>,
+ <0x6098 0xa0>,
+ <0x609c 0xa0>,
+ <0x60a0 0xa0>,
+ <0x60a4 0xa0>,
+ <0x60a8 0xa0>,
+ <0x60ac 0xa0>,
+ <0x60f0 0x0>,
+ <0x60f4 0x1>,
+ <0x60f8 0x3>,
+ <0x60fc 0x4>,
+ <0x6100 0x5>,
+ <0x6104 0x7>,
+ <0x6108 0x8>,
+ <0x610c 0x10>,
+ <0x6110 0x10>,
+ <0x6114 0x10>,
+ <0x6118 0x12>,
+ <0x611c 0x12>,
+ <0x6120 0x12>,
+ <0x6124 0x12>,
+ <0x6128 0x12>,
+ <0x612c 0x12>,
+ <0x6170 0x0>,
+ <0x6174 0x0>,
+ <0x6178 0x0>,
+ <0x617c 0x0>,
+ <0x6180 0x0>,
+ <0x6184 0x0>,
+ <0x6188 0x0>,
+ <0x618c 0x0>,
+ <0x6190 0x0>,
+ <0x6194 0x0>,
+ <0x6198 0x0>,
+ <0x619c 0x0>,
+ <0x61a0 0x0>,
+ <0x61a4 0x0>,
+ <0x61a8 0x0>,
+ <0x61ac 0x0>,
+ <0x6270 0x0>,
+ <0x6274 0x1>,
+ <0x6278 0x2>,
+ <0x627c 0x4>,
+ <0x6280 0x4>,
+ <0x6284 0x6>,
+ <0x6288 0x6>,
+ <0x628c 0x18>,
+ <0x6290 0x1a>,
+ <0x6294 0x1a>,
+ <0x6298 0x1e>,
+ <0x629c 0x1e>,
+ <0x62a0 0x1e>,
+ <0x62a4 0x1e>,
+ <0x62a8 0x1e>,
+ <0x62ac 0x1e>,
+ <0x62f0 0x1e>,
+ <0x62f4 0x24>,
+ <0x62f8 0x2a>,
+ <0x62fc 0x2c>,
+ <0x6300 0x2d>,
+ <0x6304 0x33>,
+ <0x6308 0x34>,
+ <0x630c 0x3a>,
+ <0x6310 0x3c>,
+ <0x6314 0x44>,
+ <0x6318 0x48>,
+ <0x631c 0x48>,
+ <0x6320 0x48>,
+ <0x6324 0x48>,
+ <0x6328 0x48>,
+ <0x632c 0x48>,
+ <0x6370 0x48>,
+ <0x6374 0x4d>,
+ <0x6378 0x52>,
+ <0x637c 0x56>,
+ <0x6380 0x59>,
+ <0x6384 0x63>,
+ <0x6388 0x68>,
+ <0x638c 0x70>,
+ <0x6390 0x78>,
+ <0x6394 0x88>,
+ <0x6398 0x90>,
+ <0x639c 0x90>,
+ <0x63a0 0x90>,
+ <0x63a4 0x90>,
+ <0x63a8 0x90>,
+ <0x63ac 0x90>,
+ <0x67a0 0x0>,
+ <0x67a4 0x8e>,
+ <0x67a8 0xa0>,
+ <0x67b0 0x0>,
+ <0x67b4 0x1e>,
+ <0x67b8 0xc6>,
+ <0x67d0 0x0>,
+ <0x67dc 0x4>,
+ <0x67e0 0x8>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6b48 0x330331>,
+ <0x6b4c 0x81>,
+ <0x6b50 0x1313>,
+ <0x6b64 0x121155>,
+ <0x6b68 0xea880920>,
+ <0x6b70 0x10100101>,
+ <0x6b74 0xc0c0000>,
+ <0x6b78 0xc0c0000>,
+ <0x6b80 0x20012001>,
+ <0x6b84 0x20012001>,
+ <0x6c00 0x5>,
+ <0x6c04 0x0>,
+ <0x6c08 0x5>,
+ <0x6c0c 0x0>,
+ <0x6c10 0x5>,
+ <0x6c14 0x0>,
+ <0x6c18 0x5>,
+ <0x6c1c 0x0>,
+ <0x6c20 0x5>,
+ <0x6c24 0x0>,
+ <0x6c28 0x0>,
+ <0x6c2c 0x0>,
+ <0x6c30 0x0>,
+ <0x6c34 0x0>,
+ <0x6c38 0x0>,
+ <0x6c3c 0x0>,
+ <0x6c40 0x0>,
+ <0x6c44 0x0>,
+ <0x6c48 0x0>,
+ <0x6c4c 0x0>,
+ <0x6c50 0x0>,
+ <0x6c54 0x0>,
+ <0x6c58 0x0>,
+ <0x6c5c 0x0>,
+ <0x6c60 0x0>,
+ <0x6c64 0x0>,
+ <0x6c68 0x0>,
+ <0x6c6c 0x0>,
+ <0x6c70 0x0>,
+ <0x6c74 0x0>,
+ <0x6c78 0x0>,
+ <0x6c7c 0x0>,
+ <0x6c80 0x0>,
+ <0x6c84 0x0>,
+ <0x6c88 0x0>,
+ <0x6c8c 0x0>,
+ <0x6c90 0x0>,
+ <0x6c94 0x0>,
+ <0x6c98 0x0>,
+ <0x6c9c 0x0>,
+ <0x6ca0 0x0>,
+ <0x6ca4 0x0>,
+ <0x6ca8 0x0>,
+ <0x6cac 0x0>,
+ <0x6cb0 0x0>,
+ <0x6cb4 0x0>,
+ <0x6cb8 0x0>,
+ <0x6cbc 0x0>,
+ <0x6cc0 0x0>,
+ <0x6cc4 0x0>,
+ <0x6cc8 0x0>,
+ <0x6ccc 0x0>,
+ <0x6cd0 0x0>,
+ <0x6cd4 0x0>,
+ <0x6cd8 0x0>,
+ <0x6cdc 0x0>,
+ <0x6ce0 0x0>,
+ <0x6ce4 0x0>,
+ <0x6ce8 0x0>,
+ <0x6cec 0x0>,
+ <0x6cf0 0x0>,
+ <0x6cf4 0x0>,
+ <0x6cf8 0x0>,
+ <0x6cfc 0x0>,
+ <0x6d00 0x8>,
+ <0x6d04 0x0>,
+ <0x6d08 0x8>,
+ <0x6d0c 0x0>,
+ <0x6d10 0x7>,
+ <0x6d14 0x0>,
+ <0x6d18 0x3>,
+ <0x6d1c 0x2>,
+ <0x6d20 0x4>,
+ <0x6d24 0x0>,
+ <0x6d28 0x4>,
+ <0x6d2c 0x0>,
+ <0x6d30 0x6>,
+ <0x6d34 0x0>,
+ <0x6d38 0x9>,
+ <0x6d3c 0x0>,
+ <0x6d40 0x0>,
+ <0x6d44 0x1>,
+ <0x6d48 0x4>,
+ <0x6d4c 0x0>,
+ <0x6d50 0x4>,
+ <0x6d54 0x0>,
+ <0x6d58 0x0>,
+ <0x6d5c 0x0>,
+ <0x6d60 0x0>,
+ <0x6d64 0x0>,
+ <0x6d68 0x0>,
+ <0x6d6c 0x0>,
+ <0x6d70 0x0>,
+ <0x6d74 0x0>,
+ <0x6d78 0x0>,
+ <0x6d7c 0x0>,
+ <0x6d80 0x0>,
+ <0x6d84 0x0>,
+ <0x6d88 0x0>,
+ <0x6d8c 0x0>,
+ <0x6d90 0x0>,
+ <0x6d94 0x0>,
+ <0x6d98 0x0>,
+ <0x6d9c 0x0>,
+ <0x6da0 0x0>,
+ <0x6da4 0x0>,
+ <0x6da8 0x0>,
+ <0x6dac 0x0>,
+ <0x6db0 0x0>,
+ <0x6db4 0x0>,
+ <0x6db8 0x0>,
+ <0x6dbc 0x0>,
+ <0x6dc0 0x0>,
+ <0x6dc4 0x0>,
+ <0x6dc8 0x0>,
+ <0x6dcc 0x0>,
+ <0x6dd0 0x0>,
+ <0x6dd4 0x0>,
+ <0x6dd8 0x0>,
+ <0x6ddc 0x0>,
+ <0x6de0 0x0>,
+ <0x6de4 0x0>,
+ <0x6de8 0x0>,
+ <0x6dec 0x0>,
+ <0x6df0 0x0>,
+ <0x6df4 0x0>,
+ <0x6df8 0x0>,
+ <0x6dfc 0x0>;
+};
diff --git a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi
index c724ce5a8ad9..714bdf48da6c 100644
--- a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi
@@ -147,6 +147,9 @@
dpdm-supply = <&qusb_phy0>;
+ qcom,thermal-mitigation
+ = <3000000 1500000 1000000 500000>;
+
qcom,chgr@1000 {
reg = <0x1000 0x100>;
interrupts = <0x2 0x10 0x0 IRQ_TYPE_NONE>,
diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi
index 596a713a9ad0..deccd14d5d85 100644
--- a/arch/arm/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996.dtsi
@@ -781,6 +781,7 @@
reg-names = "cc_base";
vdd_dig-supply = <&pm8994_s1_corner>;
#clock-cells = <1>;
+ #reset-cells = <1>;
};
clock_mmss: qcom,mmsscc@8c0000 {
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-cdp.dtsi
index aeb9b1c0207f..ed29dd9e1508 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-cdp.dtsi
@@ -92,22 +92,27 @@
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_active
- &cam_sensor_rear_active>;
+ &cam_sensor_rear_active
+ &cam_actuator_vaf_active>;
pinctrl-1 = <&cam_sensor_mclk0_suspend
- &cam_sensor_rear_suspend>;
+ &cam_sensor_rear_suspend
+ &cam_actuator_vaf_suspend>;
gpios = <&tlmm 13 0>,
<&tlmm 30 0>,
<&pmcobalt_gpios 20 0>,
- <&tlmm 29 0>;
+ <&tlmm 29 0>,
+ <&tlmm 27 0>;
qcom,gpio-reset = <1>;
qcom,gpio-vdig = <2>;
qcom,gpio-vana = <3>;
- qcom,gpio-req-tbl-num = <0 1 2 3>;
- qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-vaf = <4>;
+ qcom,gpio-req-tbl-num = <0 1 2 3 4>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
"CAM_RESET0",
"CAM_VDIG",
- "CAM_VANA";
+ "CAM_VANA",
+ "CAM_VAF";
qcom,sensor-position = <0>;
qcom,sensor-mode = <0>;
qcom,cci-master = <0>;
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-mtp.dtsi
index 3887999e9bab..485bc560eef5 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-mtp.dtsi
@@ -92,22 +92,27 @@
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_active
- &cam_sensor_rear_active>;
+ &cam_sensor_rear_active
+ &cam_actuator_vaf_active>;
pinctrl-1 = <&cam_sensor_mclk0_suspend
- &cam_sensor_rear_suspend>;
+ &cam_sensor_rear_suspend
+ &cam_actuator_vaf_suspend>;
gpios = <&tlmm 13 0>,
<&tlmm 30 0>,
<&pmcobalt_gpios 20 0>,
- <&tlmm 29 0>;
+ <&tlmm 29 0>,
+ <&tlmm 27 0>;
qcom,gpio-reset = <1>;
qcom,gpio-vdig = <2>;
qcom,gpio-vana = <3>;
- qcom,gpio-req-tbl-num = <0 1 2 3>;
- qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-vaf = <4>;
+ qcom,gpio-req-tbl-num = <0 1 2 3 4>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
"CAM_RESET0",
"CAM_VDIG",
- "CAM_VANA";
+ "CAM_VANA",
+ "CAM_VAF";
qcom,sensor-position = <0>;
qcom,sensor-mode = <0>;
qcom,cci-master = <0>;
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi
index a3911ea7a89d..b11c68ae543e 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi
@@ -48,7 +48,7 @@
"csi_src_clk", "csi_clk", "cphy_csid_clk",
"csiphy_timer_src_clk", "csiphy_timer_clk",
"camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk";
- qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 269333333 0
+ qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0
0 256000000 0>;
status = "ok";
};
@@ -80,7 +80,7 @@
"csi_src_clk", "csi_clk", "cphy_csid_clk",
"csiphy_timer_src_clk", "csiphy_timer_clk",
"camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk";
- qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 269333333 0
+ qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0
0 256000000 0>;
status = "ok";
};
@@ -112,7 +112,7 @@
"csi_src_clk", "csi_clk", "cphy_csid_clk",
"csiphy_timer_src_clk", "csiphy_timer_clk",
"camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk";
- qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 269333333 0
+ qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0
0 256000000 0>;
status = "ok";
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi
index a8b047a0e0b3..d1a8ae03cde2 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi
@@ -173,7 +173,7 @@
synaptics,avdd-current = <20000>;
pinctrl-names = "pmx_ts_active", "pmx_ts_suspend";
pinctrl-0 = <&ts_active>;
- pinctrl-1 = <&ts_suspend>;
+ pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
synaptics,display-coords = <0 0 1439 2559>;
synaptics,panel-coords = <0 0 1439 2559>;
synaptics,reset-gpio = <&tlmm 89 0x00>;
@@ -316,6 +316,21 @@
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
};
+&dsi_sharp_1080_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_jdi_1080_vid {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply_no_labibb>;
+ qcom,5v-boost-gpio = <&tlmm 51 0>;
+};
+
&mdss_hdmi_tx {
pinctrl-names = "hdmi_hpd_active", "hdmi_ddc_active", "hdmi_cec_active",
"hdmi_active", "hdmi_sleep";
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-mdss-panels.dtsi
index fc6c4d2eadd7..43d6e3b84cec 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-mdss-panels.dtsi
@@ -22,6 +22,8 @@
#include "dsi-panel-sharp-dsc-4k-cmd.dtsi"
#include "dsi-panel-jdi-dualmipi-video.dtsi"
#include "dsi-panel-jdi-dualmipi-cmd.dtsi"
+#include "dsi-panel-sharp-1080p-cmd.dtsi"
+#include "dsi-panel-jdi-1080p-video.dtsi"
&soc {
dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -135,3 +137,15 @@
qcom,mdss-dsi-t-clk-post = <0x06>;
qcom,mdss-dsi-t-clk-pre = <0x22>;
};
+
+&dsi_sharp_1080_cmd {
+ qcom,mdss-dsi-panel-timings = [00 17 04 05 09 09 05 06 04 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x06>;
+ qcom,mdss-dsi-t-clk-pre = <0x21>;
+};
+
+&dsi_jdi_1080_vid {
+ qcom,mdss-dsi-panel-timings = [00 1b 05 06 0a 0c 05 07 05 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x07>;
+ qcom,mdss-dsi-t-clk-pre = <0x27>;
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi
index a99ce727c195..7f1f2c10f6c4 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-mdss.dtsi
@@ -44,7 +44,8 @@
/* VBIF QoS remapper settings*/
qcom,mdss-vbif-qos-rt-setting = <1 2 2 2>;
- qcom,vbif-settings = <0x00ac 0x00000040>;
+ qcom,vbif-settings = <0x00ac 0x00000040>,
+ <0x00d0 0x00001010>; /* v1 only */
qcom,mdss-has-panic-ctrl;
qcom,mdss-per-pipe-panic-luts = <0x000f>,
@@ -57,9 +58,8 @@
qcom,max-bandwidth-high-kbps = <6700000>;
qcom,max-bandwidth-per-pipe-kbps = <2400000>;
qcom,max-clk-rate = <412500000>;
- /* OT settings and bw for v1, revisit for v2 */
- qcom,mdss-default-ot-rd-limit = <16>;
- qcom,mdss-default-ot-wr-limit = <16>;
+ qcom,mdss-default-ot-rd-limit = <32>;
+ qcom,mdss-default-ot-wr-limit = <32>;
qcom,mdss-dram-channels = <2>;
qcom,mdss-pipe-vig-off = <0x00005000 0x00007000
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi
index aaf9aed30e7f..ba25d2f07736 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi
@@ -174,7 +174,7 @@
synaptics,avdd-current = <20000>;
pinctrl-names = "pmx_ts_active", "pmx_ts_suspend";
pinctrl-0 = <&ts_active>;
- pinctrl-1 = <&ts_suspend>;
+ pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
synaptics,display-coords = <0 0 1439 2559>;
synaptics,panel-coords = <0 0 1439 2559>;
synaptics,reset-gpio = <&tlmm 89 0x00>;
@@ -341,6 +341,21 @@
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
};
+&dsi_sharp_1080_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_jdi_1080_vid {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply_no_labibb>;
+ qcom,5v-boost-gpio = <&tlmm 51 0>;
+};
+
&i2c_7 {
status = "okay";
qcom,smb138x@8 {
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
index 4cbd17f80cb8..24e23d00d697 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
@@ -1543,18 +1543,31 @@
};
};
- ts_suspend: ts_suspend {
+ ts_reset_suspend: ts_reset_suspend {
mux {
- pins = "gpio89", "gpio125";
+ pins = "gpio89";
function = "gpio";
};
config {
- pins = "gpio89", "gpio125";
+ pins = "gpio89";
drive-strength = <2>;
bias-pull-down;
};
};
+
+ ts_int_suspend: ts_int_suspend {
+ mux {
+ pins = "gpio125";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio125";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
};
sdc2_clk_on: sdc2_clk_on {
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-pm.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-pm.dtsi
index b5d3a85f9b15..6103f4c2b304 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-pm.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-pm.dtsi
@@ -292,103 +292,404 @@
qcom,ipc-bit-offset = <1>;
qcom,gic-parent = <&intc>;
- qcom,gic-map = <2 216>, /* tsens_upper_lower_int */
- <79 379>, /* qusb2phy_dmse_hv_prim */
- <80 384>, /* qusb2phy_dmse_hv_sec */
- <52 275>, /* qmp_usb3_lfps_rxterm_irq */
- <87 358>, /* ee0_krait_hlos_spmi_periph_irq */
- <49 212>, /* usb30_power_event_irq */
- <0xff 19>, /* arch_timer */
- <0xff 39>, /* arch_mem_timer */
- <0xff 483>, /* smp2p */
- <0xff 190>, /* smp2p */
- <0xff 210>, /* smp2p */
- <0xff 146>, /* msm_serial0 */
- <0xff 195>, /* ngd_slim_irq */
- <0xff 75>, /* ARM64 */
- <0xff 76>, /* ARM64 */
- <0xff 73>, /* ARM64 */
- <0xff 74>, /* ARM64 */
- <0xff 67>, /* OSM */
- <0xff 68>, /* OSM */
- <0xff 365>, /* ipa */
- <0xff 464>, /* gsi */
- <0xff 54>, /* gladiator-error */
- <0xff 481>, /* qcom,smd-modem */
- <0xff 188>, /* qcom,smd-adsp */
- <0xff 208>, /* qcom,smd-dsps */
- <0xff 484>, /* qcom,glink-smem-native-xprt-modem */
- <0xff 189>, /* qcom,glink-smem-native-xprt-adsp */
- <0xff 211>, /* qcom,glink-smem-native-xprt-dsps */
- <0xff 200>, /* qcom,glink-smem-native-xprt-rpm */
- <0xff 380>, /* qcom,glink-mailbox-xprt-spss */
- <0xff 157>, /* mmc0 */
- <0xff 253>, /* c0a4900.sdhci */
- <0xff 297>, /* ufshcd */
- <0xff 194>, /* adsp */
- <0xff 480>, /* modem */
- <0xff 490>, /* tsens_interrupt */
- <0xff 477>, /* tsens_critical_interrupt */
- <0xff 462>, /* tsens_critical_interrupt */
- <0xff 38>, /* lmh-interrupt */
- <0xff 422>, /* slpi */
- <0xff 35>, /* apps_wdog_bark */
- <0xff 22>, /* arm-pmu */
- <0xff 317>, /* cpr3 */
- <0xff 203>, /* 7781b8.qcom,mpm */
- <0xff 261>, /* arm-smmu */
- <0xff 263>, /* arm-smmu */
- <0xff 405>, /* arm-smmu-context-fault */
- <0xff 258>, /* arm-smmu-context-fault */
- <0xff 425>, /* arm-smmu-context-fault */
- <0xff 426>, /* arm-smmu-context-fault */
- <0xff 427>, /* arm-smmu-context-fault */
- <0xff 428>, /* arm-smmu-context-fault */
- <0xff 429>, /* arm-smmu-context-fault */
- <0xff 430>, /* arm-smmu-context-fault */
- <0xff 431>, /* arm-smmu-context-fault */
- <0xff 295>, /* arm-smmu-context-fault */
- <0xff 298>, /* arm-smmu-context-fault */
- <0xff 299>, /* arm-smmu-context-fault */
- <0xff 300>, /* arm-smmu-context-fault */
- <0xff 276>, /* arm-smmu-context-fault */
- <0xff 277>, /* arm-smmu-context-fault */
- <0xff 361>, /* arm-smmu-context-fault */
- <0xff 362>, /* arm-smmu-"ontext-fault */
- <0xff 110>, /* csiphy */
- <0xff 111>, /* csiphy */
- <0xff 112>, /* csiphy */
- <0xff 328>, /* csid */
- <0xff 329>, /* csid */
- <0xff 330>, /* csid */
- <0xff 331>, /* csid */
- <0xff 326>, /* */
- <0xff 341>, /* ispif */
- <0xff 346>, /* vfe */
- <0xff 347>, /* vfe */
- <0xff 327>, /* cci */
- <0xff 319>, /* msm_vidc */
- <0xff 332>, /* kgsl-3d0 */
- <0xff 115>, /* MDSS */
- <0xff 131>, /* i2c-msm-v2-irq */
- <0xff 163>, /* dwc3 */
- <0xff 240>, /* tlmm */
- <0xff 310>, /* pcie20_global_int */
- <0xff 323>, /* lpass_slimbus1_core_ee1_irq */
- <0xff 437>, /* pcie20_0_int_msi_dev0 */
- <0xff 196>, /* lpass_aud_slimbus_bam_ee1_irq */
- <0xff 215>, /* o_bimc_intr */
- <0xff 280>, /* pcie20_intd */
- <0xff 324>, /* lpass_qca_slimbus_bam_ee1_irq */
- <0xff 432>, /* smmu_Cirpt[8] */
- <0xff 433>, /* smmu_Cirpt[9] */
- <0xff 461>, /* o_ocimem_nonsec_irq */
- <0xff 69>, /* o_pwr_dcvsh_interrupt */
- <0xff 70>, /* o_perf_dcvsh_interrupt */
- <0xff 166>, /* o_lm_int_2qgic */
- <0xff 238>, /* crypto_bam_irq[0] */
- <0xff 132>; /* qup_irq */
-
+ qcom,gic-map =
+ <0x1f 212>, /* usb30_power_event_irq */
+ <0x2 216>, /* tsens1_upper_lower_int */
+ <0x34 275>, /* qmp_usb3_lfps_rxterm_irq_cx */
+ <0x57 358>, /* spmi_periph_irq[0] */
+ <0x4f 379>, /* usb2phy_intr */
+ <0x50 384>, /* sp_rmb_sp2soc_irq */
+ <0xff 16>, /* APC0_qgicQTmrHypPhysIrptReq */
+ <0xff 17>, /* APC3_qgicQTmrSecPhysIrptReq */
+ <0xff 18>, /* APC0_qgicQTmrNonSecPhysIrptReq */
+ <0xff 19>, /* APC3_qgicQTmrVirtIrptReq */
+ <0xff 20>, /* APC0_dbgCommRxFull */
+ <0xff 21>, /* APC3_dbgCommTxEmpty */
+ <0xff 22>, /* APC0_qgicPerfMonIrptReq */
+ <0xff 23>, /* corespm_vote_int[7] */
+ <0xff 24>, /* APC0_qgicExtFaultIrptReq */
+ <0xff 28>, /* qgicWakeupSync */
+ <0xff 29>, /* APCC_cti_SPI_intx */
+ <0xff 30>, /* APCC_cti_SPI_inty */
+ <0xff 32>, /* l2spm_vote_int[0] */
+ <0xff 33>, /* l2spm_vote_int[1] */
+ <0xff 34>, /* APCC_qgicL2ErrorIrptReq */
+ <0xff 35>, /* WDT_barkInt */
+ <0xff 36>, /* WDT_biteExpired */
+ <0xff 39>, /* QTMR_qgicFrm0VirtIrq */
+ <0xff 40>, /* QTMR_qgicFrm0PhyIrq */
+ <0xff 41>, /* QTMR_qgicFrm1PhyIrq */
+ <0xff 42>, /* QTMR_qgicFrm2PhyIrq */
+ <0xff 43>, /* QTMR_qgicFrm3PhyIrq */
+ <0xff 44>, /* QTMR_qgicFrm4PhyIrq */
+ <0xff 45>, /* QTMR_qgicFrm5PhyIrq */
+ <0xff 46>, /* QTMR_qgicFrm6PhyIrq */
+ <0xff 47>, /* rbif_Irq[0] */
+ <0xff 48>, /* rbif_Irq[1] */
+ <0xff 52>, /* cci_spm_vote_summary_int */
+ <0xff 54>, /* ~nERRORIRQ */
+ <0xff 55>, /* nEVNTCNTOVERFLOW_cci */
+ <0xff 56>, /* QTMR_qgicFrm0VirtIrq */
+ <0xff 57>, /* QTMR_qgicFrm0PhyIrq */
+ <0xff 58>, /* QTMR_qgicFrm1PhyIrq */
+ <0xff 59>, /* QTMR_qgicFrm2PhyIrq */
+ <0xff 60>, /* QTMR_qgicFrm3PhyIrq */
+ <0xff 61>, /* QTMR_qgicFrm4PhyIrq */
+ <0xff 62>, /* QTMR_qgicFrm5PhyIrq */
+ <0xff 63>, /* QTMR_qgicFrm6PhyIrq */
+ <0xff 64>, /* wakeup_counter_irq_OR */
+ <0xff 65>, /* apc0_vs_alarm */
+ <0xff 66>, /* apc1_vs_alarm */
+ <0xff 67>, /* o_pwr_osm_irq */
+ <0xff 68>, /* o_perf_osm_irq */
+ <0xff 69>, /* o_pwr_dcvsh_interrupt */
+ <0xff 70>, /* o_perf_dcvsh_interrupt */
+ <0xff 73>, /* L2_EXTERRIRQ_C0 */
+ <0xff 74>, /* L2_EXTERRIRQ_C1 */
+ <0xff 75>, /* L2_INTERRIRQ_C0 */
+ <0xff 76>, /* L2_INTERRIRQ_C1 */
+ <0xff 77>, /* L2SPM_svicInt[0] */
+ <0xff 78>, /* L2SPM_svicInt[1] */
+ <0xff 79>, /* L2SPM_svicIntSwDone[0] */
+ <0xff 80>, /* L2SPM_svicIntSwDone[1] */
+ <0xff 81>, /* l2_avs_err[0] */
+ <0xff 82>, /* l2_avs_err[1] */
+ <0xff 83>, /* l2_avs_ack[0] */
+ <0xff 84>, /* l2_avs_ack[1] */
+ <0xff 96>, /* uart_dm_intr */
+ <0xff 97>, /* uart_dm_intr */
+ <0xff 98>, /* o_qm_interrupt */
+ <0xff 100>, /* jpeg_vbif_irpt */
+ <0xff 101>, /* processor_1_user_int */
+ <0xff 102>, /* processor_1_kernel_int */
+ <0xff 106>, /* dir_conn_irq_lpa_dsp_2 */
+ <0xff 107>, /* dir_conn_irq_lpa_dsp_1 */
+ <0xff 109>, /* camss_vbif_0_irq */
+ <0xff 110>, /* csiphy_irq */
+ <0xff 111>, /* csiphy_irq */
+ <0xff 112>, /* csiphy_irq */
+ <0xff 115>, /* mdp_irq */
+ <0xff 116>, /* vbif_irpt */
+ <0xff 117>, /* dir_conn_irq_lpa_dsp_0 */
+ <0xff 119>, /* lcc_audio_wrapper_q6 */
+ <0xff 122>, /* PIMEM TPDM BC interrupt */
+ <0xff 123>, /* PIMEM TPDM TC interrupt */
+ <0xff 124>, /* dir_conn_irq_sensors_1 */
+ <0xff 125>, /* dir_conn_irq_sensors_0 */
+ <0xff 126>, /* qup_irq */
+ <0xff 127>, /* qup_irq */
+ <0xff 128>, /* qup_irq */
+ <0xff 129>, /* qup_irq */
+ <0xff 130>, /* qup_irq */
+ <0xff 131>, /* qup_irq */
+ <0xff 132>, /* qup_irq */
+ <0xff 133>, /* qup_irq */
+ <0xff 134>, /* qup_irq */
+ <0xff 135>, /* qup_irq */
+ <0xff 136>, /* qup_irq */
+ <0xff 137>, /* qup_irq */
+ <0xff 138>, /* qup_irq */
+ <0xff 139>, /* uart_dm_intr */
+ <0xff 140>, /* uart_dm_intr */
+ <0xff 141>, /* uart_dm_intr */
+ <0xff 145>, /* uart_dm_intr */
+ <0xff 146>, /* uart_dm_intr */
+ <0xff 147>, /* uart_dm_intr */
+ <0xff 148>, /* osmmu_Cirpt[4] */
+ <0xff 149>, /* osmmu_Cirpt[5] */
+ <0xff 151>, /* tsif_irq[0] */
+ <0xff 152>, /* tsif_irq[1] */
+ <0xff 153>, /* tspp_irq */
+ <0xff 154>, /* bam_irq */
+ <0xff 155>, /* dir_conn_irq_lpa_dsp_5 */
+ <0xff 156>, /* dir_conn_irq_lpa_dsp_4 */
+ <0xff 157>, /* sdcc_irq */
+ <0xff 158>, /* sdcc_irq */
+ <0xff 159>, /* lpass_qos_apps_interrupt */
+ <0xff 160>, /* smmu_PMIrpt */
+ <0xff 161>, /* sdcc_irq */
+ <0xff 162>, /* sdcc_irq */
+ <0xff 163>, /* usb30_ctrl_irq[0] */
+ <0xff 164>, /* usb30_bam_irq */
+ <0xff 165>, /* usb30_hs_phy_irq */
+ <0xff 166>, /* o_lm_int_2qgic */
+ <0xff 167>, /* pcie20_inta */
+ <0xff 168>, /* pcie20_intb */
+ <0xff 169>, /* smmu_Cirpt[12] */
+ <0xff 170>, /* pcie20_intc */
+ <0xff 171>, /* pcie20_intd */
+ <0xff 172>, /* dcvs_int(8) */
+ <0xff 173>, /* dcvs_int(9) */
+ <0xff 184>, /* dir_conn_irq_lpa_dsp_3 */
+ <0xff 185>, /* camss_vbif_2_irq */
+ <0xff 186>, /* mnoc_obs_mainFault */
+ <0xff 188>, /* q6ss_irq_out(4) */
+ <0xff 189>, /* q6ss_irq_out(5) */
+ <0xff 190>, /* q6ss_irq_out(6) */
+ <0xff 191>, /* q6ss_irq_out(7) */
+ <0xff 192>, /* audio_out0_irq */
+ <0xff 194>, /* q6ss_wdog_exp_irq */
+ <0xff 195>, /* lpass_slimbus_core_ee1_irq */
+ <0xff 196>, /* lpass_slimbus_bam_ee1_irq */
+ <0xff 197>, /* resampler_irq[0] */
+ <0xff 199>, /* qdss_usb_trace_bam_irq */
+ <0xff 200>, /* rpm_ipc[4] */
+ <0xff 201>, /* rpm_ipc[5] */
+ <0xff 202>, /* rpm_ipc[6] */
+ <0xff 203>, /* rpm_ipc[7] */
+ <0xff 204>, /* rpm_ipc[20] */
+ <0xff 205>, /* rpm_ipc[21] */
+ <0xff 206>, /* rpm_ipc[22] */
+ <0xff 207>, /* rpm_ipc[23] */
+ <0xff 208>, /* q6ss_irq_out(4) */
+ <0xff 209>, /* q6ss_irq_out(5) */
+ <0xff 210>, /* q6ss_irq_out(6) */
+ <0xff 211>, /* q6ss_irq_out(7) */
+ <0xff 213>, /* secure_wdog_bark_irq */
+ <0xff 214>, /* tsens1_tsens_max_min_int */
+ <0xff 215>, /* o_bimc_intr[0] */
+ <0xff 217>, /* ocimem_nonsec_irq */
+ <0xff 218>, /* sscaon_tmr_timeout_irq */
+ <0xff 219>, /* q6ss_irq_out(28) */
+ <0xff 220>, /* spmi_protocol_irq */
+ <0xff 221>, /* q6ss_irq_out(29) */
+ <0xff 222>, /* q6ss_irq_out(30) */
+ <0xff 223>, /* spdm_offline_irq */
+ <0xff 224>, /* spdm_realtime_irq */
+ <0xff 225>, /* snoc_obs_mainFault */
+ <0xff 226>, /* cnoc_obs_mainFault */
+ <0xff 227>, /* o_ss_xpu3_sec_intr */
+ <0xff 228>, /* o_tcsr_xpu3_non_sec_summary_intr */
+ <0xff 229>, /* o_timeout_slave_kpss_summary_intr */
+ <0xff 230>, /* o_tcsr_vmidmt_client_sec_summary_intr */
+ <0xff 231>, /* o_tcsr_vmidmt_client_non_sec */
+ <0xff 232>, /* o_tcsr_vmidmt_cfg_sec_summary_intr */
+ <0xff 233>, /* o_tcsr_vmidmt_cfg_non_sec */
+ <0xff 234>, /* q6ss_irq_out(31) */
+ <0xff 235>, /* cpr_irq[0] */
+ <0xff 236>, /* crypto_core_irq[0] */
+ <0xff 237>, /* crypto_core_irq[1] */
+ <0xff 238>, /* crypto_bam_irq[0] */
+ <0xff 239>, /* crypto_bam_irq[1] */
+ <0xff 240>, /* summary_irq_hmss */
+ <0xff 241>, /* dir_conn_irq_hmss_7 */
+ <0xff 242>, /* dir_conn_irq_hmss_6 */
+ <0xff 243>, /* dir_conn_irq_hmss_5 */
+ <0xff 244>, /* dir_conn_irq_hmss_4 */
+ <0xff 245>, /* dir_conn_irq_hmss_3 */
+ <0xff 246>, /* dir_conn_irq_hmss_2 */
+ <0xff 247>, /* dir_conn_irq_hmss_1 */
+ <0xff 248>, /* dir_conn_irq_hmss_0 */
+ <0xff 249>, /* summary_irq_hmss_tz */
+ <0xff 250>, /* cpr_irq[3] */
+ <0xff 251>, /* cpr_irq[2] */
+ <0xff 252>, /* cpr_irq[1] */
+ <0xff 253>, /* sdcc_pwr_cmd_irq */
+ <0xff 254>, /* sdio_wakeup_irq */
+ <0xff 255>, /* cpr_irq[0] */
+ <0xff 256>, /* smmu_Cirpt[13] */
+ <0xff 257>, /* smmu_Cirpt[14] */
+ <0xff 258>, /* smmu_Cirpt[0] */
+ <0xff 259>, /* sdcc_pwr_cmd_irq */
+ <0xff 260>, /* sdio_wakeup_irq */
+ <0xff 261>, /* o_tcsr_mmu_nsgcfglrpt_summary_intr */
+ <0xff 262>, /* o_tcsr_mmu_gcfglrpt_summary_intr */
+ <0xff 263>, /* o_tcsr_mmu_nsglrpt_summary_intr */
+ <0xff 264>, /* o_tcsr_mmu_glrpt_summary_intr */
+ <0xff 265>, /* vbif_irpt */
+ <0xff 266>, /* smmu_PMIrpt */
+ <0xff 267>, /* smmu_Cirpt[3] */
+ <0xff 268>, /* q6ss_irq_out(31) */
+ <0xff 269>, /* rpm_wdog_expired_irq */
+ <0xff 270>, /* bam_irq */
+ <0xff 271>, /* bam_irq */
+ <0xff 272>, /* q6ss_irq_out(28) */
+ <0xff 273>, /* q6ss_irq_out(29) */
+ <0xff 274>, /* q6ss_irq_out(30) */
+ <0xff 276>, /* osmmu_Cirpt [4] */
+ <0xff 277>, /* osmmu_Cirpt [5] */
+ <0xff 278>, /* usb30_ctrl_irq[1] */
+ <0xff 279>, /* osmmu_Cirpt [6] */
+ <0xff 280>, /* osmmu_Cirpt [7] */
+ <0xff 281>, /* osmmu_Cirpt [8] */
+ <0xff 282>, /* osmmu_Cirpt [9] */
+ <0xff 283>, /* osmmu_Cirpt [10] */
+ <0xff 284>, /* osmmu_Cirpt [11] */
+ <0xff 285>, /* osmmu_Cirpt [12] */
+ <0xff 286>, /* osmmu_Cirpt [13] */
+ <0xff 287>, /* osmmu_Cirpt [14] */
+ <0xff 288>, /* osmmu_Cirpt [15] */
+ <0xff 289>, /* ufs_ice_sec_level_irq */
+ <0xff 290>, /* cpr_irq[4] */
+ <0xff 291>, /* smmu_Cirpt[2] */
+ <0xff 292>, /* osmmu_Cirpt [16] */
+ <0xff 293>, /* osmmu_Cirpt [17] */
+ <0xff 294>, /* osmmu_Cirpt [18] */
+ <0xff 295>, /* osmmu_Cirpt [0] */
+ <0xff 296>, /* osmmu_PMIrpt */
+ <0xff 297>, /* ufs_intrq */
+ <0xff 298>, /* osmmu_Cirpt [1] */
+ <0xff 299>, /* osmmu_Cirpt [2] */
+ <0xff 300>, /* osmmu_Cirpt [3] */
+ <0xff 301>, /* smmu_Cirpt[1] */
+ <0xff 302>, /* qdss_etrbytecnt_irq */
+ <0xff 303>, /* smmu_Cirpt[0] */
+ <0xff 304>, /* osmmu_Cirpt [19] */
+ <0xff 305>, /* osmmu_Cirpt [20] */
+ <0xff 306>, /* osmmu_Cirpt [21] */
+ <0xff 307>, /* osmmu_Cirpt [22] */
+ <0xff 308>, /* osmmu_Cirpt [23] */
+ <0xff 310>, /* pcie20_global_int */
+ <0xff 311>, /* pcie20_int_edma_int */
+ <0xff 316>, /* lpass_hdmitx_interrupt_ext */
+ <0xff 317>, /* rbif_irq */
+ <0xff 318>, /* gpu_cc_gpu_cx_gds_hw_ctrl_irq_out */
+ <0xff 319>, /* VENUS_IRQ */
+ <0xff 323>, /* lpass_slimbus1_core_ee1_irq */
+ <0xff 324>, /* lpass_slimbus1_bam_ee1_irq */
+ <0xff 325>, /* camss_irq18 */
+ <0xff 326>, /* camss_irq0 */
+ <0xff 327>, /* camss_irq1 */
+ <0xff 328>, /* camss_irq2 */
+ <0xff 329>, /* camss_irq3 */
+ <0xff 330>, /* camss_irq4 */
+ <0xff 331>, /* camss_irq5 */
+ <0xff 332>, /* GC_SYS_irq_0 */
+ <0xff 333>, /* GC_SYS_irq_1 */
+ <0xff 334>, /* GC_SYS_irq_2 */
+ <0xff 335>, /* GC_SYS_irq_3 */
+ <0xff 336>, /* camss_irq13 */
+ <0xff 337>, /* camss_irq14 */
+ <0xff 338>, /* camss_irq15 */
+ <0xff 339>, /* camss_irq16 */
+ <0xff 340>, /* camss_irq17 */
+ <0xff 341>, /* camss_irq6 */
+ <0xff 342>, /* smmu_Cirpt[15] */
+ <0xff 343>, /* bam_irq[0] */
+ <0xff 344>, /* uart_dm_intr */
+ <0xff 345>, /* camss_irq7 */
+ <0xff 346>, /* camss_irq8 */
+ <0xff 347>, /* camss_irq9 */
+ <0xff 348>, /* camss_irq10 */
+ <0xff 350>, /* camss_irq12 */
+ <0xff 351>, /* sif_aud_dec_out_irq_ext */
+ <0xff 356>, /* vbif_nrt_irpt */
+ <0xff 357>, /* Nonfatal pIMEM interrupt */
+ <0xff 359>, /* spmi_periph_irq[1] */
+ <0xff 360>, /* fatal pIMEM interrupt */
+ <0xff 361>, /* osmmu_Cirpt[0] */
+ <0xff 362>, /* osmmu_Cirpt[1] */
+ <0xff 363>, /* osmmu_Cirpt[2] */
+ <0xff 364>, /* osmmu_Cirpt[3] */
+ <0xff 365>, /* ipa_irq(0) */
+ <0xff 366>, /* osmmu_PMIrpt */
+ <0xff 380>, /* sp_sp2apps_irq[0] */
+ <0xff 381>, /* sp_sp2apps_irq[1] */
+ <0xff 382>, /* sp_sp2apps_irq[2] */
+ <0xff 383>, /* sp_sp2apps_irq[3] */
+ <0xff 385>, /* osmmu_CIrpt[12] */
+ <0xff 386>, /* osmmu_CIrpt[13] */
+ <0xff 387>, /* osmmu_CIrpt[14] */
+ <0xff 388>, /* osmmu_CIrpt[15] */
+ <0xff 389>, /* osmmu_CIrpt[16] */
+ <0xff 390>, /* osmmu_CIrpt[17] */
+ <0xff 391>, /* osmmu_CIrpt[18] */
+ <0xff 392>, /* osmmu_CIrpt[19] */
+ <0xff 393>, /* o_dcc_crc_fail_int */
+ <0xff 395>, /* aggre1_obs_mainfault */
+ <0xff 396>, /* aggr1_smmu_cirpt[0] */
+ <0xff 397>, /* aggr1_smmu_cirpt[1] */
+ <0xff 398>, /* aggr1_smmu_cirpt[2] */
+ <0xff 399>, /* aggr1_smmu_cirpt[3] */
+ <0xff 400>, /* aggr1_smmu_cirpt[4] */
+ <0xff 401>, /* aggr1_smmu_cirpt[5] */
+ <0xff 402>, /* aggr1_smmu_cirpt[6] */
+ <0xff 403>, /* aggr1_smmu_pmirpt */
+ <0xff 404>, /* aggre2noc_obs_mainFault */
+ <0xff 405>, /* osmmu_CIrpt[0] */
+ <0xff 406>, /* osmmu_CIrpt[1] */
+ <0xff 407>, /* osmmu_CIrpt[2] */
+ <0xff 408>, /* osmmu_CIrpt[3] */
+ <0xff 409>, /* osmmu_CIrpt[4] */
+ <0xff 410>, /* osmmu_CIrpt[5] */
+ <0xff 411>, /* o_dcc_task_done_int */
+ <0xff 412>, /* vsense_alarm_irq */
+ <0xff 413>, /* osmmu_PMIrpt */
+ <0xff 414>, /* pmic_arb_trans_done_irq[0] */
+ <0xff 415>, /* pmic_arb_trans_done_irq[1] */
+ <0xff 416>, /* rpm_ipc[28] */
+ <0xff 417>, /* rpm_ipc[29] */
+ <0xff 418>, /* rpm_ipc[30] */
+ <0xff 419>, /* rpm_ipc[31] */
+ <0xff 420>, /* qup_irq */
+ <0xff 421>, /* qup_irq */
+ <0xff 422>, /* wd_bite_apps */
+ <0xff 423>, /* lpass_qos_apps_interrupt */
+ <0xff 424>, /* ipa_irq(2) */
+ <0xff 425>, /* smmu_Cirpt[1] */
+ <0xff 426>, /* smmu_Cirpt[2] */
+ <0xff 427>, /* smmu_Cirpt[3] */
+ <0xff 428>, /* smmu_Cirpt[4] */
+ <0xff 429>, /* smmu_Cirpt[5] */
+ <0xff 430>, /* smmu_Cirpt[6] */
+ <0xff 431>, /* smmu_Cirpt[7] */
+ <0xff 432>, /* smmu_Cirpt[8] */
+ <0xff 433>, /* smmu_Cirpt[9] */
+ <0xff 434>, /* smmu_Cirpt[10] */
+ <0xff 435>, /* smmu_Cirpt[11] */
+ <0xff 436>, /* smmu_Cirpt[16] */
+ <0xff 437>, /* pcie20_0_int_msi_dev0 */
+ <0xff 438>, /* pcie20_0_int_msi_dev1 */
+ <0xff 439>, /* pcie20_0_int_msi_dev2 */
+ <0xff 440>, /* pcie20_0_int_msi_dev3 */
+ <0xff 441>, /* pcie20_0_int_msi_dev4 */
+ <0xff 442>, /* pcie20_0_int_msi_dev5 */
+ <0xff 443>, /* pcie20_0_int_msi_dev6 */
+ <0xff 444>, /* pcie20_0_int_msi_dev7 */
+ <0xff 445>, /* o_wcss_apps_intr[0] */
+ <0xff 446>, /* o_wcss_apps_intr[1] */
+ <0xff 447>, /* o_wcss_apps_intr[2] */
+ <0xff 448>, /* o_wcss_apps_intr[3] */
+ <0xff 449>, /* o_wcss_apps_intr[4] */
+ <0xff 450>, /* o_wcss_apps_intr[5] */
+ <0xff 452>, /* o_wcss_apps_intr[6] */
+ <0xff 453>, /* o_wcss_apps_intr[7] */
+ <0xff 454>, /* o_wcss_apps_intr[8] */
+ <0xff 455>, /* o_wcss_apps_intr[9] */
+ <0xff 456>, /* o_wcss_apps_intr[10] */
+ <0xff 457>, /* o_wcss_apps_intr[11] */
+ <0xff 458>, /* o_wcss_apps_intr[12] */
+ <0xff 461>, /* o_ocimem_nonsec_irq */
+ <0xff 462>, /* tsens1_tsens_critical_int */
+ <0xff 463>, /* aggr1_smmu_cirpt[7] */
+ <0xff 464>, /* ipa_bam_irq(0) */
+ <0xff 465>, /* ipa_bam_irq(2) */
+ <0xff 466>, /* ssc_uart_int */
+ <0xff 468>, /* cri_cm_irq_tz */
+ <0xff 469>, /* cri_cm_irq_hyp */
+ <0xff 471>, /* mmss_bimc_smmu_gds_hw_ctrl_irq_out */
+ <0xff 472>, /* gcc_gds_hw_ctrl_irq_out */
+ <0xff 473>, /* lcc_audio_core_smmu_gds_hw_ctrl */
+ <0xff 477>, /* tsens0_tsens_critical_int */
+ <0xff 478>, /* tsens0_tsens_max_min_int */
+ <0xff 480>, /* q6ss_wdog_expired_irq */
+ <0xff 481>, /* mss_ipc_out_irq[4] */
+ <0xff 482>, /* mss_ipc_out_irq[5] */
+ <0xff 483>, /* mss_ipc_out_irq[6] */
+ <0xff 484>, /* mss_ipc_out_irq[7] */
+ <0xff 485>, /* mss_ipc_out_irq[28] */
+ <0xff 486>, /* mss_ipc_out_irq[29] */
+ <0xff 487>, /* mss_ipc_out_irq[30] */
+ <0xff 488>, /* mss_ipc_out_irq[31] */
+ <0xff 489>, /* skl_core_irq */
+ <0xff 490>, /* tsens0_upper_lower_int */
+ <0xff 494>, /* osmmu_CIrpt[6] */
+ <0xff 495>, /* osmmu_CIrpt[7] */
+ <0xff 496>, /* osmmu_CIrpt[8] */
+ <0xff 497>, /* osmmu_CIrpt[9] */
+ <0xff 498>, /* osmmu_CIrpt[10] */
+ <0xff 499>, /* osmmu_CIrpt[11] */
+ <0xff 503>; /* o_bimc_intr[1] */
qcom,gpio-parent = <&tlmm>;
qcom,gpio-map = <3 1>,
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
index 3bb5943634f2..b484b94692b5 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
@@ -58,3 +58,10 @@
< 670000000 RPM_SMD_REGULATOR_LEVEL_TURBO >,
< 710000000 RPM_SMD_REGULATOR_LEVEL_TURBO >;
};
+
+&mdss_mdp {
+ qcom,vbif-settings = <0x00d0 0x00002020>;
+ qcom,max-bandwidth-low-kbps = <9400000>;
+ qcom,max-bandwidth-high-kbps = <9400000>;
+ qcom,max-bandwidth-per-pipe-kbps = <4700000>;
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
index 33e8c9c4993d..0e2cc7361e1b 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
@@ -1751,7 +1751,7 @@
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<61 512 0 0>,
- <61 512 240000 960000>;
+ <61 512 240000 800000>;
qcom,dwc-usb3-msm-tx-fifo-size = <21288>;
extcon = <&pmicobalt_pdphy>;
@@ -1766,6 +1766,7 @@
clock-names = "core_clk", "iface_clk", "bus_aggr_clk",
"utmi_clk", "sleep_clk", "xo";
+ qcom,core-clk-rate = <120000000>;
dwc3@a800000 {
compatible = "snps,dwc3";
reg = <0x0a800000 0xcd00>;
@@ -2806,7 +2807,7 @@
qcom,qsee-ipc-irq-spss {
qcom,rx-irq-clr = <0x1d08008 0x4>;
- qcom,rx-irq-clr-mask = <0x2>;
+ qcom,rx-irq-clr-mask = <0x1>;
qcom,dev-name = "qsee_ipc_irq_spss";
interrupts = <0 349 4>;
label = "spss";
@@ -2841,10 +2842,6 @@
};
&gdsc_ufs {
- clock-names = "bus_clk", "ice_clk", "unipro_clk";
- clocks = <&clock_gcc clk_gcc_ufs_axi_clk>,
- <&clock_gcc clk_gcc_ufs_ice_core_clk>,
- <&clock_gcc clk_gcc_ufs_unipro_core_clk>;
status = "ok";
};
@@ -2947,6 +2944,7 @@
#include "msmcobalt-pm.dtsi"
#include "msm-arm-smmu-cobalt.dtsi"
+#include "msm-arm-smmu-impl-defs-cobalt.dtsi"
#include "msmcobalt-ion.dtsi"
#include "msmcobalt-camera.dtsi"
#include "msmcobalt-vidc.dtsi"
diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
index 9ccf55322de1..4b3ebd3d1636 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
@@ -314,6 +314,16 @@
#clock-cells = <1>;
};
+ clock_mmss: qcom,dummycc {
+ compatible = "qcom,dummycc";
+ #clock-cells = <1>;
+ };
+
+ clock_gfx: qcom,dummycc {
+ compatible = "qcom,dummycc";
+ #clock-cells = <1>;
+ };
+
qcom,ipc-spinlock@1f40000 {
compatible = "qcom,ipc-spinlock-sfpb";
reg = <0x1f40000 0x8000>;
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index 3a9fcfc95d00..1f9740b86e43 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -11,6 +11,7 @@ CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_SCHED_HMP=y
@@ -238,8 +239,11 @@ CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_REQ_CRYPT=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_NETDEVICES=y
@@ -383,6 +387,7 @@ CONFIG_FB_MSM_MDSS=y
CONFIG_FB_MSM_MDSS_WRITEBACK=y
CONFIG_FB_MSM_MDSS_HDMI_PANEL=y
CONFIG_FB_MSM_MDSS_DP_PANEL=y
+CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
@@ -467,6 +472,7 @@ CONFIG_GSI=y
CONFIG_IPA3=y
CONFIG_RMNET_IPA3=y
CONFIG_GPIO_USB_DETECT=y
+CONFIG_SEEMP_CORE=y
CONFIG_USB_BAM=y
CONFIG_MSM_MDSS_PLL=y
CONFIG_REMOTE_SPINLOCK_MSM=y
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index a3bad54c0b5b..ba867a7573e6 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -11,6 +11,7 @@ CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
CONFIG_CGROUPS=y
CONFIG_CGROUP_DEBUG=y
CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
@@ -240,8 +241,11 @@ CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_REQ_CRYPT=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_NETDEVICES=y
@@ -386,6 +390,7 @@ CONFIG_FB_MSM_MDSS=y
CONFIG_FB_MSM_MDSS_WRITEBACK=y
CONFIG_FB_MSM_MDSS_HDMI_PANEL=y
CONFIG_FB_MSM_MDSS_DP_PANEL=y
+CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
@@ -477,6 +482,7 @@ CONFIG_GSI=y
CONFIG_IPA3=y
CONFIG_RMNET_IPA3=y
CONFIG_GPIO_USB_DETECT=y
+CONFIG_SEEMP_CORE=y
CONFIG_USB_BAM=y
CONFIG_MSM_MDSS_PLL=y
CONFIG_REMOTE_SPINLOCK_MSM=y
diff --git a/drivers/bluetooth/btfm_slim.c b/drivers/bluetooth/btfm_slim.c
index 3b3d1b2e37b1..a88ae0f59e63 100644
--- a/drivers/bluetooth/btfm_slim.c
+++ b/drivers/bluetooth/btfm_slim.c
@@ -132,7 +132,8 @@ int btfm_slim_enable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch,
/* Define the channel with below parameters */
prop.prot = SLIM_AUTO_ISO;
prop.baser = SLIM_RATE_4000HZ;
- prop.dataf = SLIM_CH_DATAF_LPCM_AUDIO;
+ prop.dataf = (rates == 48000) ? SLIM_CH_DATAF_NOT_DEFINED
+ : SLIM_CH_DATAF_LPCM_AUDIO;
prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
prop.ratem = (rates/4000);
prop.sampleszbits = 16;
diff --git a/drivers/bluetooth/btfm_slim.h b/drivers/bluetooth/btfm_slim.h
index 1161708d6a90..dbb4c563d802 100644
--- a/drivers/bluetooth/btfm_slim.h
+++ b/drivers/bluetooth/btfm_slim.h
@@ -39,7 +39,7 @@
enum {
BTFM_FM_SLIM_TX = 0,
BTFM_BT_SCO_SLIM_TX,
- BTFM_BT_SCO_SLIM_RX,
+ BTFM_BT_SCO_A2DP_SLIM_RX,
BTFM_BT_SPLIT_A2DP_SLIM_RX,
BTFM_SLIM_NUM_CODEC_DAIS
};
diff --git a/drivers/bluetooth/btfm_slim_codec.c b/drivers/bluetooth/btfm_slim_codec.c
index 2194b8cc6f6f..d7d24ff07801 100644
--- a/drivers/bluetooth/btfm_slim_codec.c
+++ b/drivers/bluetooth/btfm_slim_codec.c
@@ -102,7 +102,7 @@ int btfm_slim_dai_prepare(struct snd_pcm_substream *substream,
ch = btfmslim->tx_chs;
rxport = 0;
break;
- case BTFM_BT_SCO_SLIM_RX:
+ case BTFM_BT_SCO_A2DP_SLIM_RX:
case BTFM_BT_SPLIT_A2DP_SLIM_RX:
ch = btfmslim->rx_chs;
rxport = 1;
@@ -150,7 +150,7 @@ int btfm_slim_dai_hw_free(struct snd_pcm_substream *substream,
ch = btfmslim->tx_chs;
rxport = 0;
break;
- case BTFM_BT_SCO_SLIM_RX:
+ case BTFM_BT_SCO_A2DP_SLIM_RX:
case BTFM_BT_SPLIT_A2DP_SLIM_RX:
ch = btfmslim->rx_chs;
rxport = 1;
@@ -267,7 +267,7 @@ static int btfm_slim_dai_get_channel_map(struct snd_soc_dai *dai,
*tx_num = num;
*rx_num = 0;
break;
- case BTFM_BT_SCO_SLIM_RX:
+ case BTFM_BT_SCO_A2DP_SLIM_RX:
case BTFM_BT_SPLIT_A2DP_SLIM_RX:
if (!rx_slot || !rx_num) {
BTFMSLIM_ERR("Invalid rx_slot %p or rx_num %p",
@@ -335,7 +335,7 @@ static struct snd_soc_dai_driver btfmslim_dai[] = {
},
.ops = &btfmslim_dai_ops,
},
- { /* Bluetooth SCO NBS voice uplink: bt -> modem */
+ { /* Bluetooth SCO voice uplink: bt -> modem */
.name = "btfm_bt_sco_slim_tx",
.id = BTFM_BT_SCO_SLIM_TX,
.capture = {
@@ -350,15 +350,15 @@ static struct snd_soc_dai_driver btfmslim_dai[] = {
},
.ops = &btfmslim_dai_ops,
},
- { /* Bluetooth SCO NBS voice downlink: modem -> bt */
- .name = "btfm_bt_sco_slim_rx",
- .id = BTFM_BT_SCO_SLIM_RX,
+ { /* Bluetooth SCO voice downlink: modem -> bt or A2DP Playback */
+ .name = "btfm_bt_sco_a2dp_slim_rx",
+ .id = BTFM_BT_SCO_A2DP_SLIM_RX,
.playback = {
- .stream_name = "SCO RX Playback",
- /* 8 KHz or 16 KHz */
- .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .stream_name = "SCO A2DP RX Playback",
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000
+ | SNDRV_PCM_RATE_48000, /* 8 or 16 or 48 Khz*/
.formats = SNDRV_PCM_FMTBIT_S16_LE, /* 16 bits */
- .rate_max = 16000,
+ .rate_max = 48000,
.rate_min = 8000,
.channels_min = 1,
.channels_max = 1,
diff --git a/drivers/bluetooth/btfm_slim_wcn3990.c b/drivers/bluetooth/btfm_slim_wcn3990.c
index 3300085be9a7..7d7bd2441c6e 100644
--- a/drivers/bluetooth/btfm_slim_wcn3990.c
+++ b/drivers/bluetooth/btfm_slim_wcn3990.c
@@ -15,7 +15,7 @@
/* WCN3990 Port assignment */
struct btfmslim_ch wcn3990_rxport[] = {
- {.id = BTFM_BT_SCO_SLIM_RX, .name = "SCO_Rx",
+ {.id = BTFM_BT_SCO_A2DP_SLIM_RX, .name = "SCO_A2P_Rx",
.port = CHRK_SB_PGD_PORT_RX_SCO},
{.id = BTFM_BT_SPLIT_A2DP_SLIM_RX, .name = "A2P_Rx",
.port = CHRK_SB_PGD_PORT_RX_A2P},
diff --git a/drivers/clk/msm/Makefile b/drivers/clk/msm/Makefile
index ecf0b09bb49a..baf22bf1df9a 100644
--- a/drivers/clk/msm/Makefile
+++ b/drivers/clk/msm/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_COMMON_CLK_MSM) += clock-pll.o
obj-$(CONFIG_COMMON_CLK_MSM) += clock-alpha-pll.o
obj-$(CONFIG_COMMON_CLK_MSM) += clock-rpm.o
obj-$(CONFIG_COMMON_CLK_MSM) += clock-voter.o
+obj-$(CONFIG_COMMON_CLK_MSM) += reset.o
obj-$(CONFIG_MSM_CLK_CONTROLLER_V2) += msm-clock-controller.o
diff --git a/drivers/clk/msm/clock-gcc-8996.c b/drivers/clk/msm/clock-gcc-8996.c
index edd78e29957d..a9e0b53c3b22 100644
--- a/drivers/clk/msm/clock-gcc-8996.c
+++ b/drivers/clk/msm/clock-gcc-8996.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -31,6 +31,7 @@
#include <dt-bindings/clock/msm-clocks-8996.h>
#include <dt-bindings/clock/msm-clocks-hwio-8996.h>
+#include "reset.h"
#include "vdd-level-8996.h"
static void __iomem *virt_base;
@@ -3142,6 +3143,26 @@ static struct branch_clk gcc_aggre0_noc_mpu_cfg_ahb_clk = {
},
};
+static const struct msm_reset_map gcc_msm8996_resets[] = {
+ [QUSB2PHY_PRIM_BCR] = { 0x12038 },
+ [QUSB2PHY_SEC_BCR] = { 0x1203c },
+ [BLSP1_BCR] = { 0x17000 },
+ [BLSP2_BCR] = { 0x25000 },
+ [BOOT_ROM_BCR] = { 0x38000 },
+ [PRNG_BCR] = { 0x34000 },
+ [UFS_BCR] = { 0x75000 },
+ [USB_20_BCR] = { 0x12000 },
+ [USB_30_BCR] = { 0x0f000 },
+ [USB3_PHY_BCR] = { 0x50020 },
+ [USB3PHY_PHY_BCR] = { 0x50024 },
+ [PCIE_0_PHY_BCR] = { 0x6c01c },
+ [PCIE_1_PHY_BCR] = { 0x6d038 },
+ [PCIE_2_PHY_BCR] = { 0x6e038 },
+ [PCIE_PHY_BCR] = { 0x6f000 },
+ [PCIE_PHY_NOCSR_COM_PHY_BCR] = { 0x6f00C },
+ [PCIE_PHY_COM_BCR] = { 0x6f014 },
+};
+
static struct mux_clk gcc_debug_mux;
static struct mux_clk gcc_debug_mux_v2;
static struct clk_ops clk_ops_debug_mux;
@@ -3711,6 +3732,10 @@ static int msm_gcc_8996_probe(struct platform_device *pdev)
*/
clk_set_flags(&gcc_mmss_bimc_gfx_clk.c, CLKFLAG_RETAIN_MEM);
+ /* Register block resets */
+ msm_reset_controller_register(pdev, gcc_msm8996_resets,
+ ARRAY_SIZE(gcc_msm8996_resets), virt_base);
+
dev_info(&pdev->dev, "Registered GCC clocks.\n");
return 0;
}
diff --git a/drivers/clk/msm/clock-mmss-8996.c b/drivers/clk/msm/clock-mmss-8996.c
index ba81731ce1cb..91c871cae225 100644
--- a/drivers/clk/msm/clock-mmss-8996.c
+++ b/drivers/clk/msm/clock-mmss-8996.c
@@ -32,6 +32,7 @@
#include "vdd-level-8996.h"
#include "clock.h"
+#include "reset.h"
static void __iomem *virt_base;
static void __iomem *virt_base_gpu;
@@ -3032,6 +3033,17 @@ static struct branch_clk vmem_maxi_clk = {
},
};
+static const struct msm_reset_map mmss_msm8996_resets[] = {
+ [VIDEO_BCR] = { 0x1020 },
+ [MDSS_BCR] = { 0x2300 },
+ [CAMSS_MICRO_BCR] = { 0x3490 },
+ [CAMSS_JPEG_BCR] = { 0x35a0 },
+ [CAMSS_VFE0_BCR] = { 0x3660 },
+ [CAMSS_VFE1_BCR] = { 0x3670 },
+ [FD_BCR] = { 0x3b60 },
+ [GPU_GX_BCR] = { 0x4020 },
+};
+
static struct mux_clk mmss_gcc_dbg_clk = {
.ops = &mux_reg_ops,
.en_mask = BIT(16),
@@ -3778,6 +3790,11 @@ int msm_mmsscc_8996_probe(struct platform_device *pdev)
if (rc)
return rc;
}
+
+ /* Register block resets */
+ msm_reset_controller_register(pdev, mmss_msm8996_resets,
+ ARRAY_SIZE(mmss_msm8996_resets), virt_base);
+
dev_info(&pdev->dev, "Registered MMSS clocks.\n");
return platform_driver_register(&msm_clock_gpu_driver);
diff --git a/drivers/clk/msm/gdsc.c b/drivers/clk/msm/gdsc.c
index 5ea2a9ccd1bb..cdaba72532d4 100644
--- a/drivers/clk/msm/gdsc.c
+++ b/drivers/clk/msm/gdsc.c
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
+#include <linux/reset.h>
#include <linux/regulator/of_regulator.h>
#include <linux/slab.h>
#include <linux/clk.h>
@@ -48,7 +49,9 @@ struct gdsc {
struct regulator_desc rdesc;
void __iomem *gdscr;
struct clk **clocks;
+ struct reset_control **reset_clocks;
int clock_count;
+ int reset_count;
bool toggle_mem;
bool toggle_periph;
bool toggle_logic;
@@ -247,9 +250,8 @@ static int gdsc_enable(struct regulator_dev *rdev)
}
}
} else {
- for (i = 0; i < sc->clock_count; i++)
- if (likely(i != sc->root_clk_idx))
- clk_reset(sc->clocks[i], CLK_RESET_DEASSERT);
+ for (i = 0; i < sc->reset_count; i++)
+ reset_control_deassert(sc->reset_clocks[i]);
sc->resets_asserted = false;
}
@@ -342,9 +344,8 @@ static int gdsc_disable(struct regulator_dev *rdev)
wmb();
}
} else {
- for (i = sc->clock_count-1; i >= 0; i--)
- if (likely(i != sc->root_clk_idx))
- clk_reset(sc->clocks[i], CLK_RESET_ASSERT);
+ for (i = sc->reset_count-1; i >= 0; i--)
+ reset_control_assert(sc->reset_clocks[i]);
sc->resets_asserted = true;
}
@@ -605,6 +606,39 @@ static int gdsc_probe(struct platform_device *pdev)
}
if (!sc->toggle_logic) {
+ sc->reset_count = of_property_count_strings(pdev->dev.of_node,
+ "reset-names");
+ if (sc->reset_count == -EINVAL) {
+ sc->reset_count = 0;
+ } else if (IS_ERR_VALUE(sc->reset_count)) {
+ dev_err(&pdev->dev, "Failed to get reset reset names\n");
+ return -EINVAL;
+ }
+
+ sc->reset_clocks = devm_kzalloc(&pdev->dev,
+ sizeof(struct reset_control *) *
+ sc->reset_count,
+ GFP_KERNEL);
+ if (!sc->reset_clocks)
+ return -ENOMEM;
+
+ for (i = 0; i < sc->reset_count; i++) {
+ const char *reset_name;
+
+ of_property_read_string_index(pdev->dev.of_node,
+ "reset-names", i, &reset_name);
+ sc->reset_clocks[i] = devm_reset_control_get(&pdev->dev,
+ reset_name);
+ if (IS_ERR(sc->reset_clocks[i])) {
+ int rc = PTR_ERR(sc->reset_clocks[i]);
+
+ if (rc != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to get %s\n",
+ reset_name);
+ return rc;
+ }
+ }
+
regval &= ~SW_COLLAPSE_MASK;
writel_relaxed(regval, sc->gdscr);
diff --git a/drivers/clk/msm/reset.c b/drivers/clk/msm/reset.c
new file mode 100644
index 000000000000..41e0357aea3e
--- /dev/null
+++ b/drivers/clk/msm/reset.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/reset-controller.h>
+
+#include "reset.h"
+
+static int msm_reset(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ rcdev->ops->assert(rcdev, id);
+ udelay(1);
+ rcdev->ops->deassert(rcdev, id);
+ return 0;
+}
+
+static int
+msm_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ struct msm_reset_controller *rst;
+ const struct msm_reset_map *map;
+ u32 regval;
+
+ rst = to_msm_reset_controller(rcdev);
+ map = &rst->reset_map[id];
+
+ regval = readl_relaxed(rst->base + map->reg);
+ regval |= BIT(map->bit);
+ writel_relaxed(regval, rst->base + map->reg);
+
+ return 0;
+}
+
+static int
+msm_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ struct msm_reset_controller *rst;
+ const struct msm_reset_map *map;
+ u32 regval;
+
+ rst = to_msm_reset_controller(rcdev);
+ map = &rst->reset_map[id];
+
+ regval = readl_relaxed(rst->base + map->reg);
+ regval &= ~BIT(map->bit);
+ writel_relaxed(regval, rst->base + map->reg);
+
+ return 0;
+}
+
+struct reset_control_ops msm_reset_ops = {
+ .reset = msm_reset,
+ .assert = msm_reset_assert,
+ .deassert = msm_reset_deassert,
+};
+EXPORT_SYMBOL_GPL(msm_reset_ops);
+
+int msm_reset_controller_register(struct platform_device *pdev,
+ const struct msm_reset_map *map, unsigned int num_resets,
+ void __iomem *virt_base)
+{
+ struct msm_reset_controller *reset;
+ int ret = 0;
+
+ reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
+ if (!reset)
+ return -ENOMEM;
+
+ reset->rcdev.of_node = pdev->dev.of_node;
+ reset->rcdev.ops = &msm_reset_ops;
+ reset->rcdev.owner = pdev->dev.driver->owner;
+ reset->rcdev.nr_resets = num_resets;
+ reset->reset_map = map;
+ reset->base = virt_base;
+
+ ret = reset_controller_register(&reset->rcdev);
+ if (ret)
+ dev_err(&pdev->dev, "Failed to register with reset controller\n");
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(msm_reset_controller_register);
diff --git a/drivers/clk/msm/reset.h b/drivers/clk/msm/reset.h
new file mode 100644
index 000000000000..538a432fed60
--- /dev/null
+++ b/drivers/clk/msm/reset.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef __DRIVERS_CLK_RESET_H
+#define __DRIVERS_CLK_RESET_H
+
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+
+struct msm_reset_map {
+ unsigned int reg;
+ u8 bit;
+};
+
+struct msm_reset_controller {
+ const struct msm_reset_map *reset_map;
+ struct reset_controller_dev rcdev;
+ void __iomem *base;
+};
+
+#define to_msm_reset_controller(r) \
+ container_of(r, struct msm_reset_controller, rcdev)
+
+extern struct reset_control_ops msm_reset_ops;
+
+int msm_reset_controller_register(struct platform_device *pdev,
+ const struct msm_reset_map *map, unsigned int nr_resets,
+ void __iomem *virt_base);
+#endif
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index 3f8a3927ff92..2b0df3f0e04e 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -44,6 +44,7 @@
#include <asm/arch_timer.h>
#include <asm/cacheflush.h>
#include <asm/suspend.h>
+#include <asm/cpuidle.h>
#include "lpm-levels.h"
#include "lpm-workarounds.h"
#include <trace/events/power.h>
@@ -914,7 +915,6 @@ unlock_and_return:
}
#if !defined(CONFIG_CPU_V7)
-#include <asm/cpuidle.h>
asmlinkage int __invoke_psci_fn_smc(u64, u64, u64, u64);
bool psci_enter_sleep(struct lpm_cluster *cluster, int idx, bool from_idle)
{
@@ -976,7 +976,7 @@ bool psci_enter_sleep(struct lpm_cluster *cluster, int idx, bool from_idle)
update_debug_pc_event(CPU_ENTER, state_id,
0xdeaffeed, 0xdeaffeed, true);
stop_critical_timings();
- success = !cpu_suspend(state_id);
+ success = !arm_cpuidle_suspend(state_id);
start_critical_timings();
update_debug_pc_event(CPU_EXIT, state_id,
success, 0xdeaffeed, true);
diff --git a/drivers/crypto/msm/ice.c b/drivers/crypto/msm/ice.c
index 3e856d0bbbe9..795d553f3318 100644
--- a/drivers/crypto/msm/ice.c
+++ b/drivers/crypto/msm/ice.c
@@ -1237,6 +1237,13 @@ static void qcom_ice_debug(struct platform_device *pdev)
qcom_ice_readl(ice_dev, QCOM_ICE_REGS_NON_SEC_IRQ_MASK),
qcom_ice_readl(ice_dev, QCOM_ICE_REGS_NON_SEC_IRQ_CLR));
+ if (ICE_REV(ice_dev->ice_hw_version, MAJOR) > 2) {
+ pr_err("%s: ICE INVALID CCFG ERR STTS: 0x%08x\n",
+ ice_dev->ice_instance_type,
+ qcom_ice_readl(ice_dev,
+ QCOM_ICE_INVALID_CCFG_ERR_STTS));
+ }
+
if ((ICE_REV(ice_dev->ice_hw_version, MAJOR) > 2) ||
((ICE_REV(ice_dev->ice_hw_version, MAJOR) == 2) &&
(ICE_REV(ice_dev->ice_hw_version, MINOR) >= 1))) {
diff --git a/drivers/crypto/msm/iceregs.h b/drivers/crypto/msm/iceregs.h
index 4fa682e4a26d..b59dccb679da 100644
--- a/drivers/crypto/msm/iceregs.h
+++ b/drivers/crypto/msm/iceregs.h
@@ -39,8 +39,19 @@
#define QCOM_ICE_REGS_PARAMETERS_3 0x001C
#define QCOM_ICE_REGS_PARAMETERS_4 0x0020
#define QCOM_ICE_REGS_PARAMETERS_5 0x0024
+
+
+/* QCOM ICE v3.X only */
+#define QCOM_ICE_GENERAL_ERR_STTS 0x0040
+#define QCOM_ICE_INVALID_CCFG_ERR_STTS 0x0030
+#define QCOM_ICE_GENERAL_ERR_MASK 0x0044
+
+
+/* QCOM ICE v2.X only */
#define QCOM_ICE_REGS_NON_SEC_IRQ_STTS 0x0040
#define QCOM_ICE_REGS_NON_SEC_IRQ_MASK 0x0044
+
+
#define QCOM_ICE_REGS_NON_SEC_IRQ_CLR 0x0048
#define QCOM_ICE_REGS_STREAM1_ERROR_SYNDROME1 0x0050
#define QCOM_ICE_REGS_STREAM1_ERROR_SYNDROME2 0x0054
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 11b323e9d40c..7ad7fdfb8181 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -2647,8 +2647,10 @@ void kgsl_active_count_put(struct kgsl_device *device)
device->requested_state == KGSL_STATE_NONE) {
kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP);
kgsl_schedule_work(&device->idle_check_ws);
- } else if (!nap_on)
+ } else if (!nap_on) {
kgsl_pwrscale_update_stats(device);
+ kgsl_pwrscale_update(device);
+ }
mod_timer(&device->idle_timer,
jiffies + device->pwrctrl.interval_timeout);
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 529edb16565a..69028bd45fdd 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1110,6 +1110,17 @@ config TOUCHSCREEN_COLIBRI_VF50
To compile this driver as a module, choose M here: the
module will be called colibri_vf50_ts.
+config TOUCHSCREEN_MSTAR21XX
+ tristate "Mstar touchscreens"
+ depends on I2C
+ help
+ Say Y here if you have a mstar touchscreen.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called msg21xx_ts.
+
config TOUCHSCREEN_ROHM_BU21023
tristate "ROHM BU21023/24 Dual touch support resistive touchscreens"
depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index e04e787cea6e..e1777f11d77b 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -97,3 +97,4 @@ obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
+obj-$(CONFIG_TOUCHSCREEN_MSTAR21XX) += msg21xx_ts.o
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index d619c1d06e9e..45ce036b1693 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -3,7 +3,7 @@
* FocalTech ft5x06 TouchScreen driver.
*
* Copyright (c) 2010 Focal tech Ltd.
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -24,13 +24,19 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/gpio.h>
+#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
+#include <linux/firmware.h>
#include <linux/input/ft5x06_ts.h>
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
#include <linux/earlysuspend.h>
/* Early-suspend level */
-#define FT5X06_SUSPEND_LEVEL 1
+#define FT_SUSPEND_LEVEL 1
#endif
#define CFG_MAX_TOUCH_POINTS 5
@@ -50,33 +56,136 @@
#define POINT_READ_BUF (3 + FT_TOUCH_STEP * CFG_MAX_TOUCH_POINTS)
-/*register address*/
-#define FT5X06_REG_PMODE 0xA5
-#define FT5X06_REG_FW_VER 0xA6
-#define FT5X06_REG_POINT_RATE 0x88
-#define FT5X06_REG_THGROUP 0x80
-
-/* power register bits*/
-#define FT5X06_PMODE_ACTIVE 0x00
-#define FT5X06_PMODE_MONITOR 0x01
-#define FT5X06_PMODE_STANDBY 0x02
-#define FT5X06_PMODE_HIBERNATE 0x03
-
-#define FT5X06_VTG_MIN_UV 2600000
-#define FT5X06_VTG_MAX_UV 3300000
-#define FT5X06_I2C_VTG_MIN_UV 1800000
-#define FT5X06_I2C_VTG_MAX_UV 1800000
+/* register address*/
+#define FT_REG_DEV_MODE 0x00
+#define FT_DEV_MODE_REG_CAL 0x02
+#define FT_REG_ID 0xA3
+#define FT_REG_PMODE 0xA5
+#define FT_REG_FW_VER 0xA6
+#define FT_REG_POINT_RATE 0x88
+#define FT_REG_THGROUP 0x80
+#define FT_REG_ECC 0xCC
+#define FT_REG_RESET_FW 0x07
+
+/* power register bits */
+#define FT_PMODE_ACTIVE 0x00
+#define FT_PMODE_MONITOR 0x01
+#define FT_PMODE_STANDBY 0x02
+#define FT_PMODE_HIBERNATE 0x03
+#define FT_FACTORYMODE_VALUE 0x40
+#define FT_WORKMODE_VALUE 0x00
+#define FT_RST_CMD_REG 0xFC
+#define FT_READ_ID_REG 0x90
+#define FT_ERASE_APP_REG 0x61
+#define FT_ERASE_PANEL_REG 0x63
+#define FT_FW_START_REG 0xBF
+
+
+#define FT_VTG_MIN_UV 2600000
+#define FT_VTG_MAX_UV 3300000
+#define FT_I2C_VTG_MIN_UV 1800000
+#define FT_I2C_VTG_MAX_UV 1800000
+
+#define FT_COORDS_ARR_SIZE 4
+#define MAX_BUTTONS 4
+
+#define FT_8BIT_SHIFT 8
+#define FT_4BIT_SHIFT 4
+#define FT_FW_NAME_MAX_LEN 50
+
+#define FT5316_ID 0x0A
+#define FT5306I_ID 0x55
+
+#define FT_UPGRADE_AA 0xAA
+#define FT_UPGRADE_55 0x55
+
+/* upgrade config of FT5606 */
+#define FT5606_UPGRADE_AA_DELAY 50
+#define FT5606_UPGRADE_55_DELAY 10
+#define FT5606_UPGRADE_ID_1 0x79
+#define FT5606_UPGRADE_ID_2 0x06
+#define FT5606_UPGRADE_READID_DELAY 100
+#define FT5606_UPGRADE_EARSE_DELAY 2000
+
+/* upgrade config of FT5316 */
+#define FT5316_UPGRADE_AA_DELAY 50
+#define FT5316_UPGRADE_55_DELAY 30
+#define FT5316_UPGRADE_ID_1 0x79
+#define FT5316_UPGRADE_ID_2 0x07
+#define FT5316_UPGRADE_READID_DELAY 1
+#define FT5316_UPGRADE_EARSE_DELAY 1500
+
+/* upgrade config of FT5x06(x=2,3,4) */
+#define FT5X06_UPGRADE_AA_DELAY 50
+#define FT5X06_UPGRADE_55_DELAY 30
+#define FT5X06_UPGRADE_ID_1 0x79
+#define FT5X06_UPGRADE_ID_2 0x03
+#define FT5X06_UPGRADE_READID_DELAY 1
+#define FT5X06_UPGRADE_EARSE_DELAY 2000
+
+/* upgrade config of FT6208 */
+#define FT6208_UPGRADE_AA_DELAY 60
+#define FT6208_UPGRADE_55_DELAY 10
+#define FT6208_UPGRADE_ID_1 0x79
+#define FT6208_UPGRADE_ID_2 0x05
+#define FT6208_UPGRADE_READID_DELAY 10
+#define FT6208_UPGRADE_EARSE_DELAY 2000
+
+#define FT_UPGRADE_INFO(x, y) do { \
+ x->delay_55 = y##_UPGRADE_55_DELAY; \
+ x->delay_aa = y##_UPGRADE_AA_DELAY; \
+ x->upgrade_id_1 = y##_UPGRADE_ID_1; \
+ x->upgrade_id_2 = y##_UPGRADE_ID_2; \
+ x->delay_readid = y##_UPGRADE_READID_DELAY; \
+ x->delay_earse_flash = y##_UPGRADE_EARSE_DELAY; \
+ } while (0)
+
+#define FT_FW_MIN_SIZE 8
+#define FT_FW_MAX_SIZE 32768
+#define FT_FW_FILE_VER(x) ((x)->data[(x)->size - 2])
+#define FT_FW_CHECK(x) \
+ (((x)->data[(x)->size - 8] ^ (x)->data[(x)->size - 6]) == 0xFF \
+ && (((x)->data[(x)->size - 7] ^ (x)->data[(x)->size - 5]) == 0xFF \
+ && (((x)->data[(x)->size - 3] ^ (x)->data[(x)->size - 4]) == 0xFF)))
+
+#define FT_MAX_TRIES 5
+#define FT_RETRY_DLY 20
+
+#define FT_MAX_WR_BUF 10
+#define FT_MAX_RD_BUF 2
+#define FT_FW_PKT_LEN 128
+#define FT_FW_PKT_META_LEN 6
+#define FT_FW_PKT_DLY_MS 20
+#define FT_FW_LAST_PKT 0x6ffa
+#define FT_EARSE_DLY_MS 100
+
+#define FT_UPGRADE_LOOP 3
+#define FT_CAL_START 0x04
+#define FT_CAL_FIN 0x00
+#define FT_CAL_STORE 0x05
+#define FT_CAL_RETRY 100
+#define FT_REG_CAL 0x00
+#define FT_CAL_MASK 0x70
struct ts_event {
- u16 x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */
- u16 y[CFG_MAX_TOUCH_POINTS]; /*y coordinate */
+ u16 x[CFG_MAX_TOUCH_POINTS]; /* x coordinate */
+ u16 y[CFG_MAX_TOUCH_POINTS]; /* y coordinate */
/* touch event: 0 -- down; 1-- contact; 2 -- contact */
u8 touch_event[CFG_MAX_TOUCH_POINTS];
- u8 finger_id[CFG_MAX_TOUCH_POINTS]; /*touch ID */
+ u8 finger_id[CFG_MAX_TOUCH_POINTS]; /* touch ID */
u16 pressure;
u8 touch_point;
};
+struct upgrade_info {
+ u16 delay_aa; /* delay of write FT_UPGRADE_AA */
+ u16 delay_55; /* delay of write FT_UPGRADE_55 */
+ u8 upgrade_id_1; /* upgrade id 1 */
+ u8 upgrade_id_2; /* upgrade id 2 */
+ u16 delay_readid; /* delay of read id */
+ u16 delay_earse_flash; /* delay of earse flash */
+};
+
struct ft5x06_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
@@ -84,7 +193,12 @@ struct ft5x06_ts_data {
const struct ft5x06_ts_platform_data *pdata;
struct regulator *vdd;
struct regulator *vcc_i2c;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+ char fw_name[FT_FW_NAME_MAX_LEN];
+ bool loading_fw;
+ u8 family_id;
+#if defined(CONFIG_FB)
+ struct notifier_block fb_notif;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
struct early_suspend early_suspend;
#endif
};
@@ -149,6 +263,21 @@ static int ft5x06_i2c_write(struct i2c_client *client, char *writebuf,
return ret;
}
+static int ft5x0x_write_reg(struct i2c_client *client, u8 addr, const u8 val)
+{
+ u8 buf[2] = {0};
+
+ buf[0] = addr;
+ buf[1] = val;
+
+ return ft5x06_i2c_write(client, buf, sizeof(buf));
+}
+
+static int ft5x0x_read_reg(struct i2c_client *client, u8 addr, u8 *val)
+{
+ return ft5x06_i2c_read(client, &addr, 1, val, 1);
+}
+
static void ft5x06_report_value(struct ft5x06_ts_data *data)
{
struct ts_event *event = &data->event;
@@ -289,8 +418,8 @@ static int ft5x06_power_init(struct ft5x06_ts_data *data, bool on)
}
if (regulator_count_voltages(data->vdd) > 0) {
- rc = regulator_set_voltage(data->vdd, FT5X06_VTG_MIN_UV,
- FT5X06_VTG_MAX_UV);
+ rc = regulator_set_voltage(data->vdd, FT_VTG_MIN_UV,
+ FT_VTG_MAX_UV);
if (rc) {
dev_err(&data->client->dev,
"Regulator set_vtg failed vdd rc=%d\n", rc);
@@ -307,8 +436,8 @@ static int ft5x06_power_init(struct ft5x06_ts_data *data, bool on)
}
if (regulator_count_voltages(data->vcc_i2c) > 0) {
- rc = regulator_set_voltage(data->vcc_i2c, FT5X06_I2C_VTG_MIN_UV,
- FT5X06_I2C_VTG_MAX_UV);
+ rc = regulator_set_voltage(data->vcc_i2c, FT_I2C_VTG_MIN_UV,
+ FT_I2C_VTG_MAX_UV);
if (rc) {
dev_err(&data->client->dev,
"Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
@@ -322,19 +451,19 @@ reg_vcc_i2c_put:
regulator_put(data->vcc_i2c);
reg_vdd_set_vtg:
if (regulator_count_voltages(data->vdd) > 0)
- regulator_set_voltage(data->vdd, 0, FT5X06_VTG_MAX_UV);
+ regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
reg_vdd_put:
regulator_put(data->vdd);
return rc;
pwr_deinit:
if (regulator_count_voltages(data->vdd) > 0)
- regulator_set_voltage(data->vdd, 0, FT5X06_VTG_MAX_UV);
+ regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
regulator_put(data->vdd);
if (regulator_count_voltages(data->vcc_i2c) > 0)
- regulator_set_voltage(data->vcc_i2c, 0, FT5X06_I2C_VTG_MAX_UV);
+ regulator_set_voltage(data->vcc_i2c, 0, FT_I2C_VTG_MAX_UV);
regulator_put(data->vcc_i2c);
return 0;
@@ -349,8 +478,8 @@ static int ft5x06_ts_suspend(struct device *dev)
disable_irq(data->client->irq);
if (gpio_is_valid(data->pdata->reset_gpio)) {
- txbuf[0] = FT5X06_REG_PMODE;
- txbuf[1] = FT5X06_PMODE_HIBERNATE;
+ txbuf[0] = FT_REG_PMODE;
+ txbuf[1] = FT_PMODE_HIBERNATE;
ft5x06_i2c_write(data->client, txbuf, sizeof(txbuf));
}
@@ -371,7 +500,27 @@ static int ft5x06_ts_resume(struct device *dev)
return 0;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_FB)
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct fb_event *evdata = data;
+ int *blank;
+ struct ft5x06_ts_data *ft5x06_data =
+ container_of(self, struct ft5x06_ts_data, fb_notif);
+
+ if (evdata && evdata->data && event == FB_EVENT_BLANK &&
+ ft5x06_data && ft5x06_data->client) {
+ blank = evdata->data;
+ if (*blank == FB_BLANK_UNBLANK)
+ ft5x06_ts_resume(&ft5x06_data->client->dev);
+ else if (*blank == FB_BLANK_POWERDOWN)
+ ft5x06_ts_suspend(&ft5x06_data->client->dev);
+ }
+
+ return 0;
+}
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
static void ft5x06_ts_early_suspend(struct early_suspend *handler)
{
struct ft5x06_ts_data *data = container_of(handler,
@@ -392,23 +541,478 @@ static void ft5x06_ts_late_resume(struct early_suspend *handler)
#endif
static const struct dev_pm_ops ft5x06_ts_pm_ops = {
-#ifndef CONFIG_HAS_EARLYSUSPEND
+#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
.suspend = ft5x06_ts_suspend,
.resume = ft5x06_ts_resume,
#endif
};
#endif
+static int ft5x06_auto_cal(struct i2c_client *client)
+{
+ u8 temp = 0, i;
+
+ /* set to factory mode */
+ msleep(2 * FT_STARTUP_DLY);
+ ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
+ msleep(FT_STARTUP_DLY);
+
+ /* start calibration */
+ ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_START);
+ msleep(2 * FT_STARTUP_DLY);
+ for (i = 0; i < FT_CAL_RETRY; i++) {
+ ft5x0x_read_reg(client, FT_REG_CAL, &temp);
+ /* return to normal mode, calibration finish */
+ if (((temp & FT_CAL_MASK) >> FT_4BIT_SHIFT) == FT_CAL_FIN)
+ break;
+ }
+
+ /* calibration OK */
+ msleep(2 * FT_STARTUP_DLY);
+ ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
+ msleep(FT_STARTUP_DLY);
+
+ /* store calibration data */
+ ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_STORE);
+ msleep(2 * FT_STARTUP_DLY);
+
+ /* set to normal mode */
+ ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE);
+ msleep(2 * FT_STARTUP_DLY);
+
+ return 0;
+}
+
+static int ft5x06_get_upgrade_info(u8 family_id, struct upgrade_info *info)
+{
+ switch (family_id) {
+ case FT5306I_ID:
+ FT_UPGRADE_INFO(info, FT5X06);
+ break;
+ case FT5316_ID:
+ FT_UPGRADE_INFO(info, FT5316);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ft5x06_fw_upgrade_start(struct i2c_client *client,
+ const u8 *data, u32 data_len)
+{
+ struct ft5x06_ts_data *ts_data = i2c_get_clientdata(client);
+ struct upgrade_info info;
+ u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0};
+ u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN];
+ int rc, i, j, temp;
+ u32 pkt_num, pkt_len;
+ u8 fw_ecc;
+
+ rc = ft5x06_get_upgrade_info(ts_data->family_id, &info);
+ if (rc < 0) {
+ dev_err(&client->dev, "Cannot get upgrade information!\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < FT_UPGRADE_LOOP; i++) {
+ /* reset - write 0xaa and 0x55 to register 0xfc */
+ ft5x0x_write_reg(client, FT_RST_CMD_REG, FT_UPGRADE_AA);
+ msleep(info.delay_aa);
+
+ ft5x0x_write_reg(client, FT_RST_CMD_REG, FT_UPGRADE_55);
+ msleep(info.delay_55);
+
+ /* Enter upgrade mode */
+ w_buf[0] = FT_UPGRADE_55;
+ w_buf[1] = FT_UPGRADE_AA;
+ do {
+ i++;
+ rc = ft5x06_i2c_write(client, w_buf, 2);
+ msleep(FT_RETRY_DLY);
+ } while (rc <= 0 && i < FT_MAX_TRIES);
+
+ /* check READ_ID */
+ msleep(info.delay_readid);
+ w_buf[0] = FT_READ_ID_REG;
+ w_buf[1] = 0x00;
+ w_buf[2] = 0x00;
+ w_buf[3] = 0x00;
+
+ ft5x06_i2c_read(client, w_buf, 4, r_buf, 2);
+
+ if (r_buf[0] != info.upgrade_id_1
+ || r_buf[1] != info.upgrade_id_2) {
+ dev_err(&client->dev, "Upgrade ID mismatch(%d)\n", i);
+ } else
+ break;
+ }
+
+ if (i >= FT_UPGRADE_LOOP) {
+ dev_err(&client->dev, "Abort upgrade\n");
+ return -EIO;
+ }
+
+ /* erase app and panel paramenter area */
+ w_buf[0] = FT_ERASE_APP_REG;
+ ft5x06_i2c_write(client, w_buf, 1);
+ msleep(info.delay_earse_flash);
+
+ w_buf[0] = FT_ERASE_PANEL_REG;
+ ft5x06_i2c_write(client, w_buf, 1);
+ msleep(FT_EARSE_DLY_MS);
+
+ /* program firmware */
+ data_len = data_len - 8;
+ pkt_num = (data_len) / FT_FW_PKT_LEN;
+ pkt_len = FT_FW_PKT_LEN;
+ pkt_buf[0] = FT_FW_START_REG;
+ pkt_buf[1] = 0x00;
+ fw_ecc = 0;
+
+ for (i = 0; i < pkt_num; i++) {
+ temp = i * FT_FW_PKT_LEN;
+ pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
+ pkt_buf[3] = (u8) temp;
+ pkt_buf[4] = (u8) (pkt_len >> FT_8BIT_SHIFT);
+ pkt_buf[5] = (u8) pkt_len;
+
+ for (j = 0; j < FT_FW_PKT_LEN; j++) {
+ pkt_buf[6 + j] = data[i * FT_FW_PKT_LEN + j];
+ fw_ecc ^= pkt_buf[6 + j];
+ }
+
+ ft5x06_i2c_write(client, pkt_buf,
+ FT_FW_PKT_LEN + FT_FW_PKT_META_LEN);
+ msleep(FT_FW_PKT_DLY_MS);
+ }
+
+ /* send remaining bytes */
+ if ((data_len) % FT_FW_PKT_LEN > 0) {
+ temp = pkt_num * FT_FW_PKT_LEN;
+ pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
+ pkt_buf[3] = (u8) temp;
+ temp = (data_len) % FT_FW_PKT_LEN;
+ pkt_buf[4] = (u8) (temp >> FT_8BIT_SHIFT);
+ pkt_buf[5] = (u8) temp;
+
+ for (i = 0; i < temp; i++) {
+ pkt_buf[6 + i] = data[pkt_num * FT_FW_PKT_LEN + i];
+ fw_ecc ^= pkt_buf[6 + i];
+ }
+
+ ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
+ msleep(FT_FW_PKT_DLY_MS);
+ }
+
+ /* send the finishing packet */
+ for (i = 0; i < 6; i++) {
+ temp = FT_FW_LAST_PKT + i;
+ pkt_buf[2] = (u8) (temp >> 8);
+ pkt_buf[3] = (u8) temp;
+ temp = 1;
+ pkt_buf[4] = (u8) (temp >> 8);
+ pkt_buf[5] = (u8) temp;
+ pkt_buf[6] = data[data_len + i];
+ fw_ecc ^= pkt_buf[6];
+ ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
+ msleep(FT_FW_PKT_DLY_MS);
+ }
+
+ /* verify checksum */
+ w_buf[0] = FT_REG_ECC;
+ ft5x06_i2c_read(client, w_buf, 1, r_buf, 1);
+ if (r_buf[0] != fw_ecc) {
+ dev_err(&client->dev, "ECC error! dev_ecc=%02x fw_ecc=%02x\n",
+ r_buf[0], fw_ecc);
+ return -EIO;
+ }
+
+ /* reset */
+ w_buf[0] = FT_REG_RESET_FW;
+ ft5x06_i2c_write(client, w_buf, 1);
+ msleep(FT_STARTUP_DLY);
+
+ return 0;
+}
+
+static int ft5x06_fw_upgrade(struct device *dev, bool force)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ const struct firmware *fw = NULL;
+ int rc;
+ u8 val = 0;
+
+ rc = request_firmware(&fw, data->fw_name, dev);
+ if (rc < 0) {
+ dev_err(dev, "Request firmware failed - %s (%d)\n",
+ data->fw_name, rc);
+ return rc;
+ }
+
+ if (fw->size < FT_FW_MIN_SIZE || fw->size > FT_FW_MAX_SIZE) {
+ dev_err(dev, "Invalid firmware size (%d)\n", fw->size);
+ rc = -EIO;
+ goto rel_fw;
+ }
+
+ /* check firmware version */
+ rc = ft5x0x_read_reg(data->client, FT_REG_FW_VER, &val);
+ if (rc < 0) {
+ dev_err(dev, "Get firmware version failed\n");
+ goto rel_fw;
+ }
+
+ if (val == FT_FW_FILE_VER(fw) && !force) {
+ dev_err(dev, "No need to update (0x%x)\n", val);
+ rc = -EFAULT;
+ goto rel_fw;
+ }
+
+ dev_info(dev, "upgrade to fw ver 0x%x from 0x%x\n",
+ FT_FW_FILE_VER(fw), val);
+
+ /* start firmware upgrade */
+ if (FT_FW_CHECK(fw)) {
+ rc = ft5x06_fw_upgrade_start(data->client, fw->data, fw->size);
+ if (rc < 0)
+ dev_err(dev, "update failed (%d)\n", rc);
+ else
+ ft5x06_auto_cal(data->client);
+ } else {
+ dev_err(dev, "FW format error\n");
+ rc = -EIO;
+ }
+
+rel_fw:
+ release_firmware(fw);
+ return rc;
+}
+
+static ssize_t ft5x06_update_fw_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, 2, "%d\n", data->loading_fw);
+}
+
+static ssize_t ft5x06_update_fw_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ unsigned long val;
+ int rc;
+
+ if (size > 2)
+ return -EINVAL;
+
+ rc = kstrtoul(buf, 10, &val);
+ if (rc != 0)
+ return rc;
+
+ mutex_lock(&data->input_dev->mutex);
+ if (!data->loading_fw && val) {
+ data->loading_fw = true;
+ ft5x06_fw_upgrade(dev, false);
+ data->loading_fw = false;
+ }
+ mutex_unlock(&data->input_dev->mutex);
+
+ return size;
+}
+
+static DEVICE_ATTR(update_fw, 0664, ft5x06_update_fw_show,
+ ft5x06_update_fw_store);
+
+static ssize_t ft5x06_force_update_fw_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ unsigned long val;
+ int rc;
+
+ if (size > 2)
+ return -EINVAL;
+
+ rc = kstrtoul(buf, 10, &val);
+ if (rc != 0)
+ return rc;
+
+ mutex_lock(&data->input_dev->mutex);
+ if (!data->loading_fw && val) {
+ data->loading_fw = true;
+ ft5x06_fw_upgrade(dev, true);
+ data->loading_fw = false;
+ }
+ mutex_unlock(&data->input_dev->mutex);
+
+ return size;
+}
+
+static DEVICE_ATTR(force_update_fw, 0664, ft5x06_update_fw_show,
+ ft5x06_force_update_fw_store);
+
+static ssize_t ft5x06_fw_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, FT_FW_NAME_MAX_LEN - 1, "%s\n", data->fw_name);
+}
+
+static ssize_t ft5x06_fw_name_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+ if (size > FT_FW_NAME_MAX_LEN - 1)
+ return -EINVAL;
+
+ strlcpy(data->fw_name, buf, size);
+ if (data->fw_name[size-1] == '\n')
+ data->fw_name[size-1] = 0;
+
+ return size;
+}
+
+static DEVICE_ATTR(fw_name, 0664, ft5x06_fw_name_show, ft5x06_fw_name_store);
+
+#ifdef CONFIG_OF
+static int ft5x06_get_dt_coords(struct device *dev, char *name,
+ struct ft5x06_ts_platform_data *pdata)
+{
+ u32 coords[FT_COORDS_ARR_SIZE];
+ struct property *prop;
+ struct device_node *np = dev->of_node;
+ int coords_size, rc;
+
+ prop = of_find_property(np, name, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ coords_size = prop->length / sizeof(u32);
+ if (coords_size != FT_COORDS_ARR_SIZE) {
+ dev_err(dev, "invalid %s\n", name);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(np, name, coords, coords_size);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read %s\n", name);
+ return rc;
+ }
+
+ if (!strcmp(name, "focaltech,panel-coords")) {
+ pdata->panel_minx = coords[0];
+ pdata->panel_miny = coords[1];
+ pdata->panel_maxx = coords[2];
+ pdata->panel_maxy = coords[3];
+ } else if (!strcmp(name, "focaltech,display-coords")) {
+ pdata->x_min = coords[0];
+ pdata->y_min = coords[1];
+ pdata->x_max = coords[2];
+ pdata->y_max = coords[3];
+ } else {
+ dev_err(dev, "unsupported property %s\n", name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ft5x06_parse_dt(struct device *dev,
+ struct ft5x06_ts_platform_data *pdata)
+{
+ int rc;
+ struct device_node *np = dev->of_node;
+ struct property *prop;
+ u32 temp_val, num_buttons;
+ u32 button_map[MAX_BUTTONS];
+
+ rc = ft5x06_get_dt_coords(dev, "focaltech,panel-coords", pdata);
+ if (rc && (rc != -EINVAL))
+ return rc;
+
+ rc = ft5x06_get_dt_coords(dev, "focaltech,display-coords", pdata);
+ if (rc)
+ return rc;
+
+ pdata->i2c_pull_up = of_property_read_bool(np,
+ "focaltech,i2c-pull-up");
+
+ pdata->no_force_update = of_property_read_bool(np,
+ "focaltech,no-force-update");
+ /* reset, irq gpio info */
+ pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio",
+ 0, &pdata->reset_gpio_flags);
+ if (pdata->reset_gpio < 0)
+ return pdata->reset_gpio;
+
+ pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio",
+ 0, &pdata->irq_gpio_flags);
+ if (pdata->irq_gpio < 0)
+ return pdata->irq_gpio;
+
+ rc = of_property_read_u32(np, "focaltech,family-id", &temp_val);
+ if (!rc)
+ pdata->family_id = temp_val;
+ else
+ return rc;
+
+ prop = of_find_property(np, "focaltech,button-map", NULL);
+ if (prop) {
+ num_buttons = prop->length / sizeof(temp_val);
+ if (num_buttons > MAX_BUTTONS)
+ return -EINVAL;
+
+ rc = of_property_read_u32_array(np,
+ "focaltech,button-map", button_map,
+ num_buttons);
+ if (rc) {
+ dev_err(dev, "Unable to read key codes\n");
+ return rc;
+ }
+ }
+
+ return 0;
+}
+#else
+static int ft5x06_parse_dt(struct device *dev,
+ struct ft5x06_ts_platform_data *pdata)
+{
+ return -ENODEV;
+}
+#endif
+
static int ft5x06_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- const struct ft5x06_ts_platform_data *pdata = client->dev.platform_data;
+ struct ft5x06_ts_platform_data *pdata;
struct ft5x06_ts_data *data;
struct input_dev *input_dev;
u8 reg_value;
u8 reg_addr;
int err;
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct ft5x06_ts_platform_data), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ err = ft5x06_parse_dt(&client->dev, pdata);
+ if (err)
+ return err;
+ } else
+ pdata = client->dev.platform_data;
+
if (!pdata) {
dev_err(&client->dev, "Invalid pdata\n");
return -EINVAL;
@@ -446,9 +1050,9 @@ static int ft5x06_ts_probe(struct i2c_client *client,
__set_bit(BTN_TOUCH, input_dev->keybit);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
- input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
pdata->x_max, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
pdata->y_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
CFG_MAX_TOUCH_POINTS, 0, 0);
@@ -523,25 +1127,44 @@ static int ft5x06_ts_probe(struct i2c_client *client,
/* make sure CTP already finish startup process */
msleep(FT_STARTUP_DLY);
- /*get some register information */
- reg_addr = FT5X06_REG_FW_VER;
+ /* check the controller id */
+ reg_addr = FT_REG_ID;
err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
- if (err)
+ if (err < 0) {
dev_err(&client->dev, "version read failed");
+ return err;
+ }
+
+ dev_info(&client->dev, "Device ID = 0x%x\n", reg_value);
- dev_info(&client->dev, "[FTS] Firmware version = 0x%x\n", reg_value);
+ if (pdata->family_id != reg_value) {
+ dev_err(&client->dev, "%s:Unsupported controller\n", __func__);
+ goto free_reset_gpio;
+ }
+
+ data->family_id = reg_value;
+
+ /* get some register information */
+ reg_addr = FT_REG_FW_VER;
+ err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
+ if (err < 0)
+ dev_err(&client->dev, "version read failed");
- reg_addr = FT5X06_REG_POINT_RATE;
+ dev_info(&client->dev, "Firmware version = 0x%x\n", reg_value);
+
+ reg_addr = FT_REG_POINT_RATE;
ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
- if (err)
+ if (err < 0)
dev_err(&client->dev, "report rate read failed");
- dev_info(&client->dev, "[FTS] report rate is %dHz.\n", reg_value * 10);
- reg_addr = FT5X06_REG_THGROUP;
+ dev_dbg(&client->dev, "report rate = %dHz\n", reg_value * 10);
+
+ reg_addr = FT_REG_THGROUP;
err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
- if (err)
+ if (err < 0)
dev_err(&client->dev, "threshold read failed");
- dev_dbg(&client->dev, "[FTS] touch threshold is %d.\n", reg_value * 4);
+
+ dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4);
err = request_threaded_irq(client->irq, NULL,
ft5x06_ts_interrupt, pdata->irqflags,
@@ -551,9 +1174,36 @@ static int ft5x06_ts_probe(struct i2c_client *client,
goto free_reset_gpio;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+ err = device_create_file(&client->dev, &dev_attr_fw_name);
+ if (err) {
+ dev_err(&client->dev, "sys file creation failed\n");
+ goto irq_free;
+ }
+
+ err = device_create_file(&client->dev, &dev_attr_update_fw);
+ if (err) {
+ dev_err(&client->dev, "sys file creation failed\n");
+ goto free_fw_name_sys;
+ }
+
+ err = device_create_file(&client->dev, &dev_attr_force_update_fw);
+ if (err) {
+ dev_err(&client->dev, "sys file creation failed\n");
+ goto free_update_fw_sys;
+ }
+
+
+#if defined(CONFIG_FB)
+ data->fb_notif.notifier_call = fb_notifier_callback;
+
+ err = fb_register_client(&data->fb_notif);
+
+ if (err)
+ dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
+ err);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
- FT5X06_SUSPEND_LEVEL;
+ FT_SUSPEND_LEVEL;
data->early_suspend.suspend = ft5x06_ts_early_suspend;
data->early_suspend.resume = ft5x06_ts_late_resume;
register_early_suspend(&data->early_suspend);
@@ -561,12 +1211,18 @@ static int ft5x06_ts_probe(struct i2c_client *client,
return 0;
+free_update_fw_sys:
+ device_remove_file(&client->dev, &dev_attr_update_fw);
+free_fw_name_sys:
+ device_remove_file(&client->dev, &dev_attr_fw_name);
+irq_free:
+ free_irq(client->irq, data);
free_reset_gpio:
if (gpio_is_valid(pdata->reset_gpio))
gpio_free(pdata->reset_gpio);
free_irq_gpio:
if (gpio_is_valid(pdata->irq_gpio))
- gpio_free(pdata->reset_gpio);
+ gpio_free(pdata->irq_gpio);
pwr_off:
if (pdata->power_on)
pdata->power_on(false);
@@ -591,7 +1247,14 @@ static int ft5x06_ts_remove(struct i2c_client *client)
{
struct ft5x06_ts_data *data = i2c_get_clientdata(client);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+ device_remove_file(&client->dev, &dev_attr_force_update_fw);
+ device_remove_file(&client->dev, &dev_attr_update_fw);
+ device_remove_file(&client->dev, &dev_attr_fw_name);
+
+#if defined(CONFIG_FB)
+ if (fb_unregister_client(&data->fb_notif))
+ dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
unregister_early_suspend(&data->early_suspend);
#endif
free_irq(client->irq, data);
@@ -600,7 +1263,7 @@ static int ft5x06_ts_remove(struct i2c_client *client)
gpio_free(data->pdata->reset_gpio);
if (gpio_is_valid(data->pdata->irq_gpio))
- gpio_free(data->pdata->reset_gpio);
+ gpio_free(data->pdata->irq_gpio);
if (data->pdata->power_on)
data->pdata->power_on(false);
@@ -625,12 +1288,22 @@ static const struct i2c_device_id ft5x06_ts_id[] = {
MODULE_DEVICE_TABLE(i2c, ft5x06_ts_id);
+#ifdef CONFIG_OF
+static const struct of_device_id ft5x06_match_table[] = {
+ { .compatible = "focaltech,5x06",},
+ { },
+};
+#else
+#define ft5x06_match_table NULL
+#endif
+
static struct i2c_driver ft5x06_ts_driver = {
.probe = ft5x06_ts_probe,
.remove = __devexit_p(ft5x06_ts_remove),
.driver = {
.name = "ft5x06_ts",
.owner = THIS_MODULE,
+ .of_match_table = ft5x06_match_table,
#ifdef CONFIG_PM
.pm = &ft5x06_ts_pm_ops,
#endif
diff --git a/drivers/input/touchscreen/it7258_ts_i2c.c b/drivers/input/touchscreen/it7258_ts_i2c.c
index c60a2b5a94b0..9080a13069a8 100644
--- a/drivers/input/touchscreen/it7258_ts_i2c.c
+++ b/drivers/input/touchscreen/it7258_ts_i2c.c
@@ -1,7 +1,7 @@
/* drivers/input/touchscreen/it7258_ts_i2c.c
*
* Copyright (C) 2014 ITE Tech. Inc.
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -30,7 +30,7 @@
#include <linux/string.h>
#define MAX_BUFFER_SIZE 144
-#define DEVICE_NAME "IT7260"
+#define DEVICE_NAME "it7260"
#define SCREEN_X_RESOLUTION 320
#define SCREEN_Y_RESOLUTION 320
#define DEBUGFS_DIR_NAME "ts_debug"
@@ -99,18 +99,20 @@
#define FW_WRITE_CHUNK_SIZE 128
#define FW_WRITE_RETRY_COUNT 4
#define CHIP_FLASH_SIZE 0x8000
-#define DEVICE_READY_MAX_WAIT 10
+#define DEVICE_READY_COUNT_MAX 500
+#define DEVICE_READY_COUNT_20 20
+#define IT_I2C_WAIT_10MS 10
+#define IT_I2C_READ_RET 2
+#define IT_I2C_WRITE_RET 1
/* result of reading with BUF_QUERY bits */
#define CMD_STATUS_BITS 0x07
#define CMD_STATUS_DONE 0x00
#define CMD_STATUS_BUSY 0x01
#define CMD_STATUS_ERROR 0x02
+#define CMD_STATUS_NO_CONN 0x07
#define PT_INFO_BITS 0xF8
-#define BT_INFO_NONE 0x00
#define PT_INFO_YES 0x80
-/* no new data but finder(s) still down */
-#define BT_INFO_NONE_BUT_DOWN 0x08
#define PD_FLAGS_DATA_TYPE_BITS 0xF0
/* other types (like chip-detected gestures) exist but we do not care */
@@ -133,22 +135,21 @@
#define PINCTRL_STATE_ACTIVE "pmx_ts_active"
#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend"
#define PINCTRL_STATE_RELEASE "pmx_ts_release"
-#define IT_I2C_WAIT 1000
-struct FingerData {
+struct finger_data {
uint8_t xLo;
uint8_t hi;
uint8_t yLo;
uint8_t pressure;
} __packed;
-struct PointData {
+struct point_data {
uint8_t flags;
uint8_t palm;
- struct FingerData fd[3];
+ struct finger_data fd[3];
} __packed;
-struct IT7260_ts_platform_data {
+struct it7260_ts_platform_data {
u32 irq_gpio;
u32 irq_gpio_flags;
u32 reset_gpio;
@@ -172,10 +173,10 @@ struct IT7260_ts_platform_data {
bool low_reset;
};
-struct IT7260_ts_data {
+struct it7260_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
- const struct IT7260_ts_platform_data *pdata;
+ const struct it7260_ts_platform_data *pdata;
struct regulator *vdd;
struct regulator *avdd;
bool device_needs_wakeup;
@@ -204,44 +205,49 @@ struct IT7260_ts_data {
/* Function declarations */
static int fb_notifier_callback(struct notifier_block *self,
unsigned long event, void *data);
-static int IT7260_ts_resume(struct device *dev);
-static int IT7260_ts_suspend(struct device *dev);
+static int it7260_ts_resume(struct device *dev);
+static int it7260_ts_suspend(struct device *dev);
-static struct IT7260_ts_data *gl_ts;
-
-static int IT7260_debug_suspend_set(void *_data, u64 val)
+static int it7260_debug_suspend_set(void *_data, u64 val)
{
+ struct it7260_ts_data *ts_data = _data;
+
if (val)
- IT7260_ts_suspend(&gl_ts->client->dev);
+ it7260_ts_suspend(&ts_data->client->dev);
else
- IT7260_ts_resume(&gl_ts->client->dev);
+ it7260_ts_resume(&ts_data->client->dev);
return 0;
}
-static int IT7260_debug_suspend_get(void *_data, u64 *val)
+static int it7260_debug_suspend_get(void *_data, u64 *val)
{
- *val = gl_ts->suspended;
+ struct it7260_ts_data *ts_data = _data;
+
+ mutex_lock(&ts_data->input_dev->mutex);
+ *val = ts_data->suspended;
+ mutex_lock(&ts_data->input_dev->mutex);
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, IT7260_debug_suspend_get,
- IT7260_debug_suspend_set, "%lld\n");
+DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, it7260_debug_suspend_get,
+ it7260_debug_suspend_set, "%lld\n");
/* internal use func - does not make sure chip is ready before read */
-static bool IT7260_i2cReadNoReadyCheck(uint8_t buf_index, uint8_t *buffer,
- uint16_t buf_len)
+static int it7260_i2c_read_no_ready_check(struct it7260_ts_data *ts_data,
+ uint8_t buf_index, uint8_t *buffer, uint16_t buf_len)
{
+ int ret;
struct i2c_msg msgs[2] = {
{
- .addr = gl_ts->client->addr,
+ .addr = ts_data->client->addr,
.flags = I2C_M_NOSTART,
.len = 1,
.buf = &buf_index
},
{
- .addr = gl_ts->client->addr,
+ .addr = ts_data->client->addr,
.flags = I2C_M_RD,
.len = buf_len,
.buf = buffer
@@ -250,15 +256,20 @@ static bool IT7260_i2cReadNoReadyCheck(uint8_t buf_index, uint8_t *buffer,
memset(buffer, 0xFF, buf_len);
- return i2c_transfer(gl_ts->client->adapter, msgs, 2);
+ ret = i2c_transfer(ts_data->client->adapter, msgs, 2);
+ if (ret < 0)
+ dev_err(&ts_data->client->dev, "i2c read failed %d\n", ret);
+
+ return ret;
}
-static bool IT7260_i2cWriteNoReadyCheck(uint8_t buf_index,
- const uint8_t *buffer, uint16_t buf_len)
+static int it7260_i2c_write_no_ready_check(struct it7260_ts_data *ts_data,
+ uint8_t buf_index, const uint8_t *buffer, uint16_t buf_len)
{
uint8_t txbuf[257];
+ int ret;
struct i2c_msg msg = {
- .addr = gl_ts->client->addr,
+ .addr = ts_data->client->addr,
.flags = 0,
.len = buf_len + 1,
.buf = txbuf
@@ -266,110 +277,178 @@ static bool IT7260_i2cWriteNoReadyCheck(uint8_t buf_index,
/* just to be careful */
if (buf_len > sizeof(txbuf) - 1) {
- dev_err(&gl_ts->client->dev, "buf length is out of limit\n");
+ dev_err(&ts_data->client->dev, "buf length is out of limit\n");
return false;
}
txbuf[0] = buf_index;
memcpy(txbuf + 1, buffer, buf_len);
- return i2c_transfer(gl_ts->client->adapter, &msg, 1);
+ ret = i2c_transfer(ts_data->client->adapter, &msg, 1);
+ if (ret < 0)
+ dev_err(&ts_data->client->dev, "i2c write failed %d\n", ret);
+
+ return ret;
}
/*
- * Device is apparently always ready for i2c but not for actual
- * register reads/writes. This function ascertains it is ready
- * for that too. the results of this call often were ignored.
+ * Device is apparently always ready for I2C communication but not for
+ * actual register reads/writes. This function checks if it is ready
+ * for that too. The results of this call often were ignored.
+ * If forever is set to TRUE, then check the device's status until it
+ * becomes ready with 500 retries at max. Otherwise retry 25 times only.
+ * If slowly is set to TRUE, then add sleep of 50 ms in each retry,
+ * otherwise don't sleep.
*/
-static bool IT7260_waitDeviceReady(bool forever, bool slowly)
+static int it7260_wait_device_ready(struct it7260_ts_data *ts_data,
+ bool forever, bool slowly)
{
uint8_t query;
- uint32_t count = DEVICE_READY_MAX_WAIT;
+ uint32_t count = DEVICE_READY_COUNT_20;
+ int ret;
+
+ if (ts_data->fw_cfg_uploading || forever)
+ count = DEVICE_READY_COUNT_MAX;
do {
- if (!IT7260_i2cReadNoReadyCheck(BUF_QUERY, &query,
- sizeof(query)))
- query = CMD_STATUS_BUSY;
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_QUERY, &query,
+ sizeof(query));
+ if (ret < 0 && ((query & CMD_STATUS_BITS)
+ == CMD_STATUS_NO_CONN))
+ continue;
- if (slowly)
- msleep(IT_I2C_WAIT);
- if (!forever)
- count--;
+ if ((query & CMD_STATUS_BITS) == CMD_STATUS_DONE)
+ break;
- } while ((query & CMD_STATUS_BUSY) && count);
+ query = CMD_STATUS_BUSY;
+ if (slowly)
+ msleep(IT_I2C_WAIT_10MS);
+ } while (--count);
- return !query;
+ return ((!(query & CMD_STATUS_BITS)) ? 0 : -ENODEV);
}
-static bool IT7260_i2cRead(uint8_t buf_index, uint8_t *buffer,
- uint16_t buf_len)
+static int it7260_i2c_read(struct it7260_ts_data *ts_data, uint8_t buf_index,
+ uint8_t *buffer, uint16_t buf_len)
{
- IT7260_waitDeviceReady(false, false);
- return IT7260_i2cReadNoReadyCheck(buf_index, buffer, buf_len);
+ int ret;
+
+ ret = it7260_wait_device_ready(ts_data, false, false);
+ if (ret < 0)
+ return ret;
+
+ return it7260_i2c_read_no_ready_check(ts_data, buf_index,
+ buffer, buf_len);
}
-static bool IT7260_i2cWrite(uint8_t buf_index, const uint8_t *buffer,
- uint16_t buf_len)
+static int it7260_i2c_write(struct it7260_ts_data *ts_data, uint8_t buf_index,
+ const uint8_t *buffer, uint16_t buf_len)
{
- IT7260_waitDeviceReady(false, false);
- return IT7260_i2cWriteNoReadyCheck(buf_index, buffer, buf_len);
+ int ret;
+
+ ret = it7260_wait_device_ready(ts_data, false, false);
+ if (ret < 0)
+ return ret;
+
+ return it7260_i2c_write_no_ready_check(ts_data, buf_index,
+ buffer, buf_len);
}
-static bool IT7260_firmware_reinitialize(u8 command)
+static int it7260_firmware_reinitialize(struct it7260_ts_data *ts_data,
+ u8 command)
{
uint8_t cmd[] = {command};
uint8_t rsp[2];
+ int ret;
- if (!IT7260_i2cWrite(BUF_COMMAND, cmd, sizeof(cmd)))
- return false;
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd, sizeof(cmd));
+ if (ret != IT_I2C_WRITE_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to write fw reinit command %d\n", ret);
+ return ret;
+ }
- if (!IT7260_i2cRead(BUF_RESPONSE, rsp, sizeof(rsp)))
- return false;
+ ret = it7260_i2c_read(ts_data, BUF_RESPONSE, rsp, sizeof(rsp));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read any response from chip %d\n", ret);
+ return ret;
+ }
/* a reply of two zero bytes signifies success */
- return !rsp[0] && !rsp[1];
+ if (rsp[0] == 0 && rsp[1] == 0)
+ return 0;
+ else
+ return -EIO;
}
-static bool IT7260_enter_exit_fw_ugrade_mode(bool enter)
+static int it7260_enter_exit_fw_ugrade_mode(struct it7260_ts_data *ts_data,
+ bool enter)
{
uint8_t cmd[] = {CMD_FIRMWARE_UPGRADE, 0, 'I', 'T', '7', '2',
'6', '0', 0x55, 0xAA};
uint8_t resp[2];
+ int ret;
cmd[1] = enter ? SUB_CMD_ENTER_FW_UPGRADE_MODE :
SUB_CMD_EXIT_FW_UPGRADE_MODE;
- if (!IT7260_i2cWrite(BUF_COMMAND, cmd, sizeof(cmd)))
- return false;
- if (!IT7260_i2cRead(BUF_RESPONSE, resp, sizeof(resp)))
- return false;
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd, sizeof(cmd));
+ if (ret != IT_I2C_WRITE_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to write CMD_FIRMWARE_UPGRADE %d\n", ret);
+ return ret;
+ }
+
+ ret = it7260_i2c_read(ts_data, BUF_RESPONSE, resp, sizeof(resp));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read any response from chip %d\n", ret);
+ return ret;
+ }
/* a reply of two zero bytes signifies success */
- return !resp[0] && !resp[1];
+ if (resp[0] == 0 && resp[1] == 0)
+ return 0;
+ else
+ return -EIO;
}
-static bool IT7260_chipSetStartOffset(uint16_t offset)
+static int it7260_set_start_offset(struct it7260_ts_data *ts_data,
+ uint16_t offset)
{
uint8_t cmd[] = {CMD_SET_START_OFFSET, 0, ((uint8_t)(offset)),
((uint8_t)((offset) >> 8))};
uint8_t resp[2];
+ int ret;
- if (!IT7260_i2cWrite(BUF_COMMAND, cmd, 4))
- return false;
-
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd, 4);
+ if (ret != IT_I2C_WRITE_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to write CMD_SET_START_OFFSET %d\n", ret);
+ return ret;
+ }
- if (!IT7260_i2cRead(BUF_RESPONSE, resp, sizeof(resp)))
- return false;
+ ret = it7260_i2c_read(ts_data, BUF_RESPONSE, resp, sizeof(resp));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read any response from chip %d\n", ret);
+ return ret;
+ }
/* a reply of two zero bytes signifies success */
- return !resp[0] && !resp[1];
+ if (resp[0] == 0 && resp[1] == 0)
+ return 0;
+ else
+ return -EIO;
}
/* write fw_length bytes from fw_data at chip offset wr_start_offset */
-static bool IT7260_fw_flash_write_verify(unsigned int fw_length,
- const uint8_t *fw_data, uint16_t wr_start_offset)
+static int it7260_fw_flash_write_verify(struct it7260_ts_data *ts_data,
+ unsigned int fw_length, const uint8_t *fw_data,
+ uint16_t wr_start_offset)
{
uint32_t cur_data_off;
@@ -399,17 +478,18 @@ static bool IT7260_fw_flash_write_verify(unsigned int fw_length,
retries++) {
/* set write offset and write the data */
- IT7260_chipSetStartOffset(
+ it7260_set_start_offset(ts_data,
wr_start_offset + cur_data_off);
- IT7260_i2cWrite(BUF_COMMAND, cmd_write,
+ it7260_i2c_write(ts_data, BUF_COMMAND, cmd_write,
cur_wr_size + 2);
/* set offset and read the data back */
- IT7260_chipSetStartOffset(
+ it7260_set_start_offset(ts_data,
wr_start_offset + cur_data_off);
- IT7260_i2cWrite(BUF_COMMAND, cmd_read,
+ it7260_i2c_write(ts_data, BUF_COMMAND, cmd_read,
sizeof(cmd_read));
- IT7260_i2cRead(BUF_RESPONSE, buf_read, cur_wr_size);
+ it7260_i2c_read(ts_data, BUF_RESPONSE, buf_read,
+ cur_wr_size);
/* verify. If success break out of retry loop */
i = 0;
@@ -421,68 +501,96 @@ static bool IT7260_fw_flash_write_verify(unsigned int fw_length,
}
/* if we've failed after all the retries, tell the caller */
if (retries == FW_WRITE_RETRY_COUNT) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"write of data offset %u failed on try %u at byte %u/%u\n",
cur_data_off, retries, i, cur_wr_size);
- return false;
+ return -EIO;
}
}
- return true;
+ return 0;
}
/*
* this code to get versions from the chip via i2c transactions, and save
* them in driver data structure.
*/
-static void IT7260_get_chip_versions(struct device *dev)
+static void it7260_get_chip_versions(struct it7260_ts_data *ts_data)
{
static const u8 cmd_read_fw_ver[] = {CMD_READ_VERSIONS,
SUB_CMD_READ_FIRMWARE_VERSION};
static const u8 cmd_read_cfg_ver[] = {CMD_READ_VERSIONS,
SUB_CMD_READ_CONFIG_VERSION};
u8 ver_fw[VERSION_LENGTH], ver_cfg[VERSION_LENGTH];
- bool ret = true;
+ int ret;
- ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_fw_ver,
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd_read_fw_ver,
sizeof(cmd_read_fw_ver));
- if (ret) {
- ret = IT7260_i2cRead(BUF_RESPONSE, ver_fw, VERSION_LENGTH);
- if (ret)
- memcpy(gl_ts->fw_ver, ver_fw + (5 * sizeof(u8)),
+ if (ret == IT_I2C_WRITE_RET) {
+ /*
+ * Sometimes, the controller may not respond immediately after
+ * writing the command, so wait for device to get ready.
+ */
+ ret = it7260_wait_device_ready(ts_data, true, false);
+ if (ret < 0)
+ dev_err(&ts_data->client->dev,
+ "failed to read chip status %d\n", ret);
+
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_RESPONSE,
+ ver_fw, VERSION_LENGTH);
+ if (ret == IT_I2C_READ_RET)
+ memcpy(ts_data->fw_ver, ver_fw + (5 * sizeof(u8)),
VER_BUFFER_SIZE * sizeof(u8));
+ else
+ dev_err(&ts_data->client->dev,
+ "failed to read fw-ver from chip %d\n", ret);
+ } else {
+ dev_err(&ts_data->client->dev,
+ "failed to write fw-read command %d\n", ret);
}
- if (!ret)
- dev_err(dev, "failed to read fw version from chip\n");
- ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_cfg_ver,
+ ret = it7260_i2c_write(ts_data, BUF_COMMAND, cmd_read_cfg_ver,
sizeof(cmd_read_cfg_ver));
- if (ret) {
- ret = IT7260_i2cRead(BUF_RESPONSE, ver_cfg, VERSION_LENGTH)
- && ret;
- if (ret)
- memcpy(gl_ts->cfg_ver, ver_cfg + (1 * sizeof(u8)),
+ if (ret == IT_I2C_WRITE_RET) {
+ /*
+ * Sometimes, the controller may not respond immediately after
+ * writing the command, so wait for device to get ready.
+ */
+ ret = it7260_wait_device_ready(ts_data, true, false);
+ if (ret < 0)
+ dev_err(&ts_data->client->dev,
+ "failed to read chip status %d\n", ret);
+
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_RESPONSE,
+ ver_cfg, VERSION_LENGTH);
+ if (ret == IT_I2C_READ_RET)
+ memcpy(ts_data->cfg_ver, ver_cfg + (1 * sizeof(u8)),
VER_BUFFER_SIZE * sizeof(u8));
+ else
+ dev_err(&ts_data->client->dev,
+ "failed to read cfg-ver from chip %d\n", ret);
+ } else {
+ dev_err(&ts_data->client->dev,
+ "failed to write cfg-read command %d\n", ret);
}
- if (!ret)
- dev_err(dev, "failed to read cfg version from chip\n");
- dev_info(dev, "Current fw{%X.%X.%X.%X} cfg{%X.%X.%X.%X}\n",
- gl_ts->fw_ver[0], gl_ts->fw_ver[1], gl_ts->fw_ver[2],
- gl_ts->fw_ver[3], gl_ts->cfg_ver[0], gl_ts->cfg_ver[1],
- gl_ts->cfg_ver[2], gl_ts->cfg_ver[3]);
+ dev_info(&ts_data->client->dev, "Current fw{%X.%X.%X.%X} cfg{%X.%X.%X.%X}\n",
+ ts_data->fw_ver[0], ts_data->fw_ver[1], ts_data->fw_ver[2],
+ ts_data->fw_ver[3], ts_data->cfg_ver[0], ts_data->cfg_ver[1],
+ ts_data->cfg_ver[2], ts_data->cfg_ver[3]);
}
-static int IT7260_cfg_upload(struct device *dev, bool force)
+static int it7260_cfg_upload(struct it7260_ts_data *ts_data, bool force)
{
const struct firmware *cfg = NULL;
int ret;
- bool success, cfg_upgrade = false;
+ bool cfg_upgrade = false;
+ struct device *dev = &ts_data->client->dev;
- ret = request_firmware(&cfg, gl_ts->cfg_name, dev);
+ ret = request_firmware(&cfg, ts_data->cfg_name, dev);
if (ret) {
dev_err(dev, "failed to get config data %s for it7260 %d\n",
- gl_ts->cfg_name, ret);
+ ts_data->cfg_name, ret);
return ret;
}
@@ -493,43 +601,59 @@ static int IT7260_cfg_upload(struct device *dev, bool force)
*/
if (force)
cfg_upgrade = true;
- else if (IT_CFG_CHECK(gl_ts->cfg_ver, cfg))
+ else if (IT_CFG_CHECK(ts_data->cfg_ver, cfg))
cfg_upgrade = true;
if (!cfg_upgrade) {
- dev_err(dev, "CFG upgrade no required ...\n");
+ dev_err(dev, "CFG upgrade not required ...\n");
+ dev_info(dev,
+ "Chip CFG : %X.%X.%X.%X Binary CFG : %X.%X.%X.%X\n",
+ ts_data->cfg_ver[0], ts_data->cfg_ver[1],
+ ts_data->cfg_ver[2], ts_data->cfg_ver[3],
+ cfg->data[cfg->size - 8], cfg->data[cfg->size - 7],
+ cfg->data[cfg->size - 6], cfg->data[cfg->size - 5]);
ret = -EFAULT;
goto out;
} else {
dev_info(dev, "Config upgrading...\n");
- disable_irq(gl_ts->client->irq);
+ disable_irq(ts_data->client->irq);
/* enter cfg upload mode */
- success = IT7260_enter_exit_fw_ugrade_mode(true);
- if (!success) {
- dev_err(dev, "Can't enter cfg upgrade mode\n");
- ret = -EIO;
+ ret = it7260_enter_exit_fw_ugrade_mode(ts_data, true);
+ if (ret < 0) {
+ dev_err(dev, "Can't enter cfg upgrade mode %d\n", ret);
+ enable_irq(ts_data->client->irq);
goto out;
}
/* flash config data if requested */
- success = IT7260_fw_flash_write_verify(cfg->size, cfg->data,
- CHIP_FLASH_SIZE - cfg->size);
- if (!success) {
- dev_err(dev, "failed to upgrade touch cfg data\n");
- IT7260_enter_exit_fw_ugrade_mode(false);
- IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_6F);
+ ret = it7260_fw_flash_write_verify(ts_data, cfg->size,
+ cfg->data, CHIP_FLASH_SIZE - cfg->size);
+ if (ret < 0) {
+ dev_err(dev,
+ "failed to upgrade touch cfg data %d\n", ret);
+ ret = it7260_enter_exit_fw_ugrade_mode(ts_data, false);
+ if (ret < 0)
+ dev_err(dev,
+ "Can't exit cfg upgrade mode%d\n", ret);
+
+ ret = it7260_firmware_reinitialize(ts_data,
+ CMD_FIRMWARE_REINIT_6F);
+ if (ret < 0)
+ dev_err(dev, "Can't reinit cfg %d\n", ret);
+
ret = -EIO;
+ enable_irq(ts_data->client->irq);
goto out;
} else {
- memcpy(gl_ts->cfg_ver, cfg->data +
+ memcpy(ts_data->cfg_ver, cfg->data +
(cfg->size - 8 * sizeof(u8)),
VER_BUFFER_SIZE * sizeof(u8));
dev_info(dev, "CFG upgrade is success. New cfg ver: %X.%X.%X.%X\n",
- gl_ts->cfg_ver[0], gl_ts->cfg_ver[1],
- gl_ts->cfg_ver[2], gl_ts->cfg_ver[3]);
+ ts_data->cfg_ver[0], ts_data->cfg_ver[1],
+ ts_data->cfg_ver[2], ts_data->cfg_ver[3]);
}
- enable_irq(gl_ts->client->irq);
+ enable_irq(ts_data->client->irq);
}
out:
@@ -538,16 +662,17 @@ out:
return ret;
}
-static int IT7260_fw_upload(struct device *dev, bool force)
+static int it7260_fw_upload(struct it7260_ts_data *ts_data, bool force)
{
const struct firmware *fw = NULL;
int ret;
- bool success, fw_upgrade = false;
+ bool fw_upgrade = false;
+ struct device *dev = &ts_data->client->dev;
- ret = request_firmware(&fw, gl_ts->fw_name, dev);
+ ret = request_firmware(&fw, ts_data->fw_name, dev);
if (ret) {
dev_err(dev, "failed to get firmware %s for it7260 %d\n",
- gl_ts->fw_name, ret);
+ ts_data->fw_name, ret);
return ret;
}
@@ -558,40 +683,55 @@ static int IT7260_fw_upload(struct device *dev, bool force)
*/
if (force)
fw_upgrade = true;
- else if (IT_FW_CHECK(gl_ts->fw_ver, fw))
+ else if (IT_FW_CHECK(ts_data->fw_ver, fw))
fw_upgrade = true;
if (!fw_upgrade) {
dev_err(dev, "FW upgrade not required ...\n");
+ dev_info(dev, "Chip FW : %X.%X.%X.%X Binary FW : %X.%X.%X.%X\n",
+ ts_data->fw_ver[0], ts_data->fw_ver[1],
+ ts_data->fw_ver[2], ts_data->fw_ver[3],
+ fw->data[8], fw->data[9], fw->data[10], fw->data[11]);
ret = -EFAULT;
goto out;
} else {
dev_info(dev, "Firmware upgrading...\n");
- disable_irq(gl_ts->client->irq);
+ disable_irq(ts_data->client->irq);
/* enter fw upload mode */
- success = IT7260_enter_exit_fw_ugrade_mode(true);
- if (!success) {
- dev_err(dev, "Can't enter fw upgrade mode\n");
- ret = -EIO;
+ ret = it7260_enter_exit_fw_ugrade_mode(ts_data, true);
+ if (ret < 0) {
+ dev_err(dev, "Can't enter fw upgrade mode %d\n", ret);
+ enable_irq(ts_data->client->irq);
goto out;
}
/* flash the firmware if requested */
- success = IT7260_fw_flash_write_verify(fw->size, fw->data, 0);
- if (!success) {
- dev_err(dev, "failed to upgrade touch firmware\n");
- IT7260_enter_exit_fw_ugrade_mode(false);
- IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_6F);
+ ret = it7260_fw_flash_write_verify(ts_data, fw->size,
+ fw->data, 0);
+ if (ret < 0) {
+ dev_err(dev,
+ "failed to upgrade touch firmware %d\n", ret);
+ ret = it7260_enter_exit_fw_ugrade_mode(ts_data, false);
+ if (ret < 0)
+ dev_err(dev,
+ "Can't exit fw upgrade mode %d\n", ret);
+
+ ret = it7260_firmware_reinitialize(ts_data,
+ CMD_FIRMWARE_REINIT_6F);
+ if (ret < 0)
+ dev_err(dev, "Can't reinit firmware %d\n", ret);
+
ret = -EIO;
+ enable_irq(ts_data->client->irq);
goto out;
} else {
- memcpy(gl_ts->fw_ver, fw->data + (8 * sizeof(u8)),
+ memcpy(ts_data->fw_ver, fw->data + (8 * sizeof(u8)),
VER_BUFFER_SIZE * sizeof(u8));
dev_info(dev, "FW upgrade is success. New fw ver: %X.%X.%X.%X\n",
- gl_ts->fw_ver[0], gl_ts->fw_ver[1],
- gl_ts->fw_ver[2], gl_ts->fw_ver[3]);
+ ts_data->fw_ver[0], ts_data->fw_ver[1],
+ ts_data->fw_ver[2], ts_data->fw_ver[3]);
}
- enable_irq(gl_ts->client->irq);
+ enable_irq(ts_data->client->irq);
}
out:
@@ -600,16 +740,18 @@ out:
return ret;
}
-static int IT7260_ts_chipLowPowerMode(const u8 sleep_type)
+static int it7260_ts_chip_low_power_mode(struct it7260_ts_data *ts_data,
+ const u8 sleep_type)
{
const uint8_t cmd_sleep[] = {CMD_PWR_CTL, 0x00, sleep_type};
uint8_t dummy;
if (sleep_type)
- IT7260_i2cWriteNoReadyCheck(BUF_COMMAND, cmd_sleep,
+ it7260_i2c_write_no_ready_check(ts_data, BUF_COMMAND, cmd_sleep,
sizeof(cmd_sleep));
else
- IT7260_i2cReadNoReadyCheck(BUF_QUERY, &dummy, sizeof(dummy));
+ it7260_i2c_read_no_ready_check(ts_data, BUF_QUERY, &dummy,
+ sizeof(dummy));
msleep(WAIT_CHANGE_MODE);
return 0;
@@ -618,32 +760,33 @@ static int IT7260_ts_chipLowPowerMode(const u8 sleep_type)
static ssize_t sysfs_fw_upgrade_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int mode = 0, ret;
- if (gl_ts->suspended) {
+ if (ts_data->suspended) {
dev_err(dev, "Device is suspended, can't flash fw!!!\n");
return -EBUSY;
}
ret = kstrtoint(buf, 10, &mode);
- if (!ret) {
+ if (ret) {
dev_err(dev, "failed to read input for sysfs\n");
return -EINVAL;
}
- mutex_lock(&gl_ts->fw_cfg_mutex);
+ mutex_lock(&ts_data->fw_cfg_mutex);
if (mode == 1) {
- gl_ts->fw_cfg_uploading = true;
- ret = IT7260_fw_upload(dev, false);
+ ts_data->fw_cfg_uploading = true;
+ ret = it7260_fw_upload(ts_data, false);
if (ret) {
dev_err(dev, "Failed to flash fw: %d", ret);
- gl_ts->fw_upgrade_result = false;
+ ts_data->fw_upgrade_result = false;
} else {
- gl_ts->fw_upgrade_result = true;
+ ts_data->fw_upgrade_result = true;
}
- gl_ts->fw_cfg_uploading = false;
+ ts_data->fw_cfg_uploading = false;
}
- mutex_unlock(&gl_ts->fw_cfg_mutex);
+ mutex_unlock(&ts_data->fw_cfg_mutex);
return count;
}
@@ -651,32 +794,33 @@ static ssize_t sysfs_fw_upgrade_store(struct device *dev,
static ssize_t sysfs_cfg_upgrade_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int mode = 0, ret;
- if (gl_ts->suspended) {
+ if (ts_data->suspended) {
dev_err(dev, "Device is suspended, can't flash cfg!!!\n");
return -EBUSY;
}
ret = kstrtoint(buf, 10, &mode);
- if (!ret) {
+ if (ret) {
dev_err(dev, "failed to read input for sysfs\n");
return -EINVAL;
}
- mutex_lock(&gl_ts->fw_cfg_mutex);
+ mutex_lock(&ts_data->fw_cfg_mutex);
if (mode == 1) {
- gl_ts->fw_cfg_uploading = true;
- ret = IT7260_cfg_upload(dev, false);
+ ts_data->fw_cfg_uploading = true;
+ ret = it7260_cfg_upload(ts_data, false);
if (ret) {
dev_err(dev, "Failed to flash cfg: %d", ret);
- gl_ts->cfg_upgrade_result = false;
+ ts_data->cfg_upgrade_result = false;
} else {
- gl_ts->cfg_upgrade_result = true;
+ ts_data->cfg_upgrade_result = true;
}
- gl_ts->fw_cfg_uploading = false;
+ ts_data->fw_cfg_uploading = false;
}
- mutex_unlock(&gl_ts->fw_cfg_mutex);
+ mutex_unlock(&ts_data->fw_cfg_mutex);
return count;
}
@@ -684,46 +828,51 @@ static ssize_t sysfs_cfg_upgrade_store(struct device *dev,
static ssize_t sysfs_fw_upgrade_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n",
- gl_ts->fw_upgrade_result);
+ ts_data->fw_upgrade_result);
}
static ssize_t sysfs_cfg_upgrade_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n",
- gl_ts->cfg_upgrade_result);
+ ts_data->cfg_upgrade_result);
}
static ssize_t sysfs_force_fw_upgrade_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int mode = 0, ret;
- if (gl_ts->suspended) {
+ if (ts_data->suspended) {
dev_err(dev, "Device is suspended, can't flash fw!!!\n");
return -EBUSY;
}
ret = kstrtoint(buf, 10, &mode);
- if (!ret) {
+ if (ret) {
dev_err(dev, "failed to read input for sysfs\n");
return -EINVAL;
}
- mutex_lock(&gl_ts->fw_cfg_mutex);
+ mutex_lock(&ts_data->fw_cfg_mutex);
if (mode == 1) {
- gl_ts->fw_cfg_uploading = true;
- ret = IT7260_fw_upload(dev, true);
+ ts_data->fw_cfg_uploading = true;
+ ret = it7260_fw_upload(ts_data, true);
if (ret) {
dev_err(dev, "Failed to force flash fw: %d", ret);
- gl_ts->fw_upgrade_result = false;
+ ts_data->fw_upgrade_result = false;
} else {
- gl_ts->fw_upgrade_result = true;
+ ts_data->fw_upgrade_result = true;
}
- gl_ts->fw_cfg_uploading = false;
+ ts_data->fw_cfg_uploading = false;
}
- mutex_unlock(&gl_ts->fw_cfg_mutex);
+ mutex_unlock(&ts_data->fw_cfg_mutex);
return count;
}
@@ -731,32 +880,33 @@ static ssize_t sysfs_force_fw_upgrade_store(struct device *dev,
static ssize_t sysfs_force_cfg_upgrade_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int mode = 0, ret;
- if (gl_ts->suspended) {
+ if (ts_data->suspended) {
dev_err(dev, "Device is suspended, can't flash cfg!!!\n");
return -EBUSY;
}
ret = kstrtoint(buf, 10, &mode);
- if (!ret) {
+ if (ret) {
dev_err(dev, "failed to read input for sysfs\n");
return -EINVAL;
}
- mutex_lock(&gl_ts->fw_cfg_mutex);
+ mutex_lock(&ts_data->fw_cfg_mutex);
if (mode == 1) {
- gl_ts->fw_cfg_uploading = true;
- ret = IT7260_cfg_upload(dev, true);
+ ts_data->fw_cfg_uploading = true;
+ ret = it7260_cfg_upload(ts_data, true);
if (ret) {
dev_err(dev, "Failed to force flash cfg: %d", ret);
- gl_ts->cfg_upgrade_result = false;
+ ts_data->cfg_upgrade_result = false;
} else {
- gl_ts->cfg_upgrade_result = true;
+ ts_data->cfg_upgrade_result = true;
}
- gl_ts->fw_cfg_uploading = false;
+ ts_data->fw_cfg_uploading = false;
}
- mutex_unlock(&gl_ts->fw_cfg_mutex);
+ mutex_unlock(&ts_data->fw_cfg_mutex);
return count;
}
@@ -764,51 +914,65 @@ static ssize_t sysfs_force_cfg_upgrade_store(struct device *dev,
static ssize_t sysfs_force_fw_upgrade_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return snprintf(buf, MAX_BUFFER_SIZE, "%d", gl_ts->fw_upgrade_result);
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, MAX_BUFFER_SIZE, "%d", ts_data->fw_upgrade_result);
}
static ssize_t sysfs_force_cfg_upgrade_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return snprintf(buf, MAX_BUFFER_SIZE, "%d", gl_ts->cfg_upgrade_result);
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, MAX_BUFFER_SIZE, "%d",
+ ts_data->cfg_upgrade_result);
}
static ssize_t sysfs_calibration_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n",
- gl_ts->calibration_success);
+ ts_data->calibration_success);
}
-static bool IT7260_chipSendCalibrationCmd(bool auto_tune_on)
+static int it7260_ts_send_calibration_cmd(struct it7260_ts_data *ts_data,
+ bool auto_tune_on)
{
uint8_t cmd_calibrate[] = {CMD_CALIBRATE, 0,
auto_tune_on ? 1 : 0, 0, 0};
- return IT7260_i2cWrite(BUF_COMMAND, cmd_calibrate,
+
+ return it7260_i2c_write(ts_data, BUF_COMMAND, cmd_calibrate,
sizeof(cmd_calibrate));
}
static ssize_t sysfs_calibration_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
uint8_t resp;
+ int ret;
- if (!IT7260_chipSendCalibrationCmd(false)) {
+ ret = it7260_ts_send_calibration_cmd(ts_data, false);
+ if (ret < 0) {
dev_err(dev, "failed to send calibration command\n");
} else {
- gl_ts->calibration_success =
- IT7260_i2cRead(BUF_RESPONSE, &resp, sizeof(resp));
+ ret = it7260_i2c_read(ts_data, BUF_RESPONSE, &resp,
+ sizeof(resp));
+ if (ret == IT_I2C_READ_RET)
+ ts_data->calibration_success = true;
/*
* previous logic that was here never called
- * IT7260_firmware_reinitialize() due to checking a
+ * it7260_firmware_reinitialize() due to checking a
* guaranteed-not-null value against null. We now
* call it. Hopefully this is OK
*/
if (!resp)
- dev_dbg(dev, "IT7260_firmware_reinitialize-> %s\n",
- IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_6F)
- ? "success" : "fail");
+ dev_dbg(dev, "it7260_firmware_reinitialize-> %s\n",
+ it7260_firmware_reinitialize(ts_data,
+ CMD_FIRMWARE_REINIT_6F) ? "success" : "fail");
}
return count;
@@ -817,21 +981,22 @@ static ssize_t sysfs_calibration_store(struct device *dev,
static ssize_t sysfs_point_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- uint8_t point_data[sizeof(struct PointData)];
- bool readSuccess;
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+ uint8_t pt_data[sizeof(struct point_data)];
+ int readSuccess;
ssize_t ret;
- readSuccess = IT7260_i2cReadNoReadyCheck(BUF_POINT_INFO, point_data,
- sizeof(point_data));
+ readSuccess = it7260_i2c_read_no_ready_check(ts_data, BUF_POINT_INFO,
+ pt_data, sizeof(pt_data));
- if (readSuccess) {
+ if (readSuccess == IT_I2C_READ_RET) {
ret = scnprintf(buf, MAX_BUFFER_SIZE,
"point_show read ret[%d]--point[%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x]\n",
- readSuccess, point_data[0], point_data[1],
- point_data[2], point_data[3], point_data[4],
- point_data[5], point_data[6], point_data[7],
- point_data[8], point_data[9], point_data[10],
- point_data[11], point_data[12], point_data[13]);
+ readSuccess, pt_data[0], pt_data[1],
+ pt_data[2], pt_data[3], pt_data[4],
+ pt_data[5], pt_data[6], pt_data[7],
+ pt_data[8], pt_data[9], pt_data[10],
+ pt_data[11], pt_data[12], pt_data[13]);
} else {
ret = scnprintf(buf, MAX_BUFFER_SIZE,
"failed to read point data\n");
@@ -844,51 +1009,57 @@ static ssize_t sysfs_point_show(struct device *dev,
static ssize_t sysfs_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
return scnprintf(buf, MAX_BUFFER_SIZE,
"fw{%X.%X.%X.%X} cfg{%X.%X.%X.%X}\n",
- gl_ts->fw_ver[0], gl_ts->fw_ver[1], gl_ts->fw_ver[2],
- gl_ts->fw_ver[3], gl_ts->cfg_ver[0], gl_ts->cfg_ver[1],
- gl_ts->cfg_ver[2], gl_ts->cfg_ver[3]);
+ ts_data->fw_ver[0], ts_data->fw_ver[1],
+ ts_data->fw_ver[2], ts_data->fw_ver[3],
+ ts_data->cfg_ver[0], ts_data->cfg_ver[1],
+ ts_data->cfg_ver[2], ts_data->cfg_ver[3]);
}
static ssize_t sysfs_sleep_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
/*
* The usefulness of this was questionable at best - we were at least
* leaking a byte of kernel data (by claiming to return a byte but not
* writing to buf. To fix this now we actually return the sleep status
*/
- *buf = gl_ts->suspended ? '1' : '0';
+ *buf = ts_data->suspended ? '1' : '0';
+
return 1;
}
static ssize_t sysfs_sleep_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int go_to_sleep, ret;
ret = kstrtoint(buf, 10, &go_to_sleep);
- /* (gl_ts->suspended == true && goToSleepVal > 0) means
+ /* (ts_data->suspended == true && goToSleepVal > 0) means
* device is already suspended and you want it to be in sleep,
- * (gl_ts->suspended == false && goToSleepVal == 0) means
+ * (ts_data->suspended == false && goToSleepVal == 0) means
* device is already active and you also want it to be active.
*/
- if ((gl_ts->suspended && go_to_sleep > 0) ||
- (!gl_ts->suspended && go_to_sleep == 0))
+ if ((ts_data->suspended && go_to_sleep > 0) ||
+ (!ts_data->suspended && go_to_sleep == 0))
dev_err(dev, "duplicate request to %s chip\n",
go_to_sleep ? "sleep" : "wake");
else if (go_to_sleep) {
- disable_irq(gl_ts->client->irq);
- IT7260_ts_chipLowPowerMode(PWR_CTL_SLEEP_MODE);
+ disable_irq(ts_data->client->irq);
+ it7260_ts_chip_low_power_mode(ts_data, PWR_CTL_SLEEP_MODE);
dev_dbg(dev, "touch is going to sleep...\n");
} else {
- IT7260_ts_chipLowPowerMode(PWR_CTL_ACTIVE_MODE);
- enable_irq(gl_ts->client->irq);
+ it7260_ts_chip_low_power_mode(ts_data, PWR_CTL_ACTIVE_MODE);
+ enable_irq(ts_data->client->irq);
dev_dbg(dev, "touch is going to wake!\n");
}
- gl_ts->suspended = go_to_sleep;
+ ts_data->suspended = go_to_sleep;
return count;
}
@@ -896,6 +1067,7 @@ static ssize_t sysfs_sleep_store(struct device *dev,
static ssize_t sysfs_cfg_name_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
char *strptr;
if (count >= MAX_BUFFER_SIZE) {
@@ -909,7 +1081,7 @@ static ssize_t sysfs_cfg_name_store(struct device *dev,
return -EINVAL;
}
- strlcpy(gl_ts->cfg_name, buf, count);
+ strlcpy(ts_data->cfg_name, buf, count);
return count;
}
@@ -917,9 +1089,11 @@ static ssize_t sysfs_cfg_name_store(struct device *dev,
static ssize_t sysfs_cfg_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- if (strnlen(gl_ts->cfg_name, MAX_BUFFER_SIZE) > 0)
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ if (strnlen(ts_data->cfg_name, MAX_BUFFER_SIZE) > 0)
return scnprintf(buf, MAX_BUFFER_SIZE, "%s\n",
- gl_ts->cfg_name);
+ ts_data->cfg_name);
else
return scnprintf(buf, MAX_BUFFER_SIZE,
"No config file name given\n");
@@ -928,6 +1102,7 @@ static ssize_t sysfs_cfg_name_show(struct device *dev,
static ssize_t sysfs_fw_name_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
char *strptr;
if (count >= MAX_BUFFER_SIZE) {
@@ -941,16 +1116,18 @@ static ssize_t sysfs_fw_name_store(struct device *dev,
return -EINVAL;
}
- strlcpy(gl_ts->fw_name, buf, count);
+ strlcpy(ts_data->fw_name, buf, count);
return count;
}
static ssize_t sysfs_fw_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- if (strnlen(gl_ts->fw_name, MAX_BUFFER_SIZE) > 0)
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
+
+ if (strnlen(ts_data->fw_name, MAX_BUFFER_SIZE) > 0)
return scnprintf(buf, MAX_BUFFER_SIZE, "%s\n",
- gl_ts->fw_name);
+ ts_data->fw_name);
else
return scnprintf(buf, MAX_BUFFER_SIZE,
"No firmware file name given\n");
@@ -997,59 +1174,47 @@ static const struct attribute_group it7260_attr_group = {
.attrs = it7260_attributes,
};
-static void IT7260_chipExternalCalibration(bool autoTuneEnabled)
-{
- uint8_t resp[2];
-
- dev_dbg(&gl_ts->client->dev, "sent calibration command -> %d\n",
- IT7260_chipSendCalibrationCmd(autoTuneEnabled));
- IT7260_waitDeviceReady(true, true);
- IT7260_i2cReadNoReadyCheck(BUF_RESPONSE, resp, sizeof(resp));
- IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_C);
-}
-
-void IT7260_sendCalibrationCmd(void)
-{
- IT7260_chipExternalCalibration(false);
-}
-EXPORT_SYMBOL(IT7260_sendCalibrationCmd);
-
-static void IT7260_ts_release_all(void)
+static void it7260_ts_release_all(struct it7260_ts_data *ts_data)
{
int finger;
- for (finger = 0; finger < gl_ts->pdata->num_of_fingers; finger++) {
- input_mt_slot(gl_ts->input_dev, finger);
- input_mt_report_slot_state(gl_ts->input_dev,
+ for (finger = 0; finger < ts_data->pdata->num_of_fingers; finger++) {
+ input_mt_slot(ts_data->input_dev, finger);
+ input_mt_report_slot_state(ts_data->input_dev,
MT_TOOL_FINGER, 0);
}
- input_report_key(gl_ts->input_dev, BTN_TOUCH, 0);
- input_sync(gl_ts->input_dev);
+ input_report_key(ts_data->input_dev, BTN_TOUCH, 0);
+ input_sync(ts_data->input_dev);
}
-static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid)
+static irqreturn_t it7260_ts_threaded_handler(int irq, void *devid)
{
- struct PointData point_data;
- struct input_dev *input_dev = gl_ts->input_dev;
+ struct point_data pt_data;
+ struct it7260_ts_data *ts_data = devid;
+ struct input_dev *input_dev = ts_data->input_dev;
u8 dev_status, finger, touch_count = 0, finger_status;
u8 pressure = FD_PRESSURE_NONE;
u16 x, y;
bool palm_detected;
+ int ret;
/* verify there is point data to read & it is readable and valid */
- IT7260_i2cReadNoReadyCheck(BUF_QUERY, &dev_status, sizeof(dev_status));
- if (!((dev_status & PT_INFO_BITS) & PT_INFO_YES))
- return IRQ_HANDLED;
- if (!IT7260_i2cReadNoReadyCheck(BUF_POINT_INFO, (void *)&point_data,
- sizeof(point_data))) {
- dev_err(&gl_ts->client->dev,
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_QUERY, &dev_status,
+ sizeof(dev_status));
+ if (ret == IT_I2C_READ_RET)
+ if (!((dev_status & PT_INFO_BITS) & PT_INFO_YES))
+ return IRQ_HANDLED;
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_POINT_INFO,
+ (void *)&pt_data, sizeof(pt_data));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
"failed to read point data buffer\n");
return IRQ_HANDLED;
}
/* Check if controller moves from idle to active state */
- if ((point_data.flags & PD_FLAGS_DATA_TYPE_BITS) !=
+ if ((pt_data.flags & PD_FLAGS_DATA_TYPE_BITS) !=
PD_FLAGS_DATA_TYPE_TOUCH) {
/*
* This code adds the touch-to-wake functionality to the ITE
@@ -1061,40 +1226,40 @@ static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid)
* schedule a work that tells the pm core to relax once the CPU
* cores are up.
*/
- if (gl_ts->device_needs_wakeup) {
- pm_stay_awake(&gl_ts->client->dev);
+ if (ts_data->device_needs_wakeup) {
+ pm_stay_awake(&ts_data->client->dev);
input_report_key(input_dev, KEY_WAKEUP, 1);
input_sync(input_dev);
input_report_key(input_dev, KEY_WAKEUP, 0);
input_sync(input_dev);
- schedule_work(&gl_ts->work_pm_relax);
+ schedule_work(&ts_data->work_pm_relax);
return IRQ_HANDLED;
}
}
- palm_detected = point_data.palm & PD_PALM_FLAG_BIT;
- if (palm_detected && gl_ts->pdata->palm_detect_en) {
+ palm_detected = pt_data.palm & PD_PALM_FLAG_BIT;
+ if (palm_detected && ts_data->pdata->palm_detect_en) {
input_report_key(input_dev,
- gl_ts->pdata->palm_detect_keycode, 1);
+ ts_data->pdata->palm_detect_keycode, 1);
input_sync(input_dev);
input_report_key(input_dev,
- gl_ts->pdata->palm_detect_keycode, 0);
+ ts_data->pdata->palm_detect_keycode, 0);
input_sync(input_dev);
}
- for (finger = 0; finger < gl_ts->pdata->num_of_fingers; finger++) {
- finger_status = point_data.flags & (0x01 << finger);
+ for (finger = 0; finger < ts_data->pdata->num_of_fingers; finger++) {
+ finger_status = pt_data.flags & (0x01 << finger);
input_mt_slot(input_dev, finger);
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
finger_status != 0);
- x = point_data.fd[finger].xLo +
- (((u16)(point_data.fd[finger].hi & 0x0F)) << 8);
- y = point_data.fd[finger].yLo +
- (((u16)(point_data.fd[finger].hi & 0xF0)) << 4);
+ x = pt_data.fd[finger].xLo +
+ (((u16)(pt_data.fd[finger].hi & 0x0F)) << 8);
+ y = pt_data.fd[finger].yLo +
+ (((u16)(pt_data.fd[finger].hi & 0xF0)) << 4);
- pressure = point_data.fd[finger].pressure & FD_PRESSURE_BITS;
+ pressure = pt_data.fd[finger].pressure & FD_PRESSURE_BITS;
if (finger_status) {
if (pressure >= FD_PRESSURE_LIGHT) {
@@ -1114,35 +1279,66 @@ static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid)
return IRQ_HANDLED;
}
-static void IT7260_ts_work_func(struct work_struct *work)
+static void it7260_ts_work_func(struct work_struct *work)
{
- pm_relax(&gl_ts->client->dev);
+ struct it7260_ts_data *ts_data = container_of(work,
+ struct it7260_ts_data, work_pm_relax);
+
+ pm_relax(&ts_data->client->dev);
}
-static int IT7260_chipIdentify(void)
+static int it7260_ts_chip_identify(struct it7260_ts_data *ts_data)
{
static const uint8_t cmd_ident[] = {CMD_IDENT_CHIP};
static const uint8_t expected_id[] = {0x0A, 'I', 'T', 'E', '7',
'2', '6', '0'};
uint8_t chip_id[10] = {0,};
+ int ret;
- IT7260_waitDeviceReady(false, false);
+ /*
+ * Sometimes, the controller may not respond immediately after
+ * writing the command, so wait for device to get ready.
+ * FALSE means to retry 20 times at max to read the chip status.
+ * TRUE means to add delay in each retry.
+ */
+ ret = it7260_wait_device_ready(ts_data, false, true);
+ if (ret < 0) {
+ dev_err(&ts_data->client->dev,
+ "failed to read chip status %d\n", ret);
+ return ret;
+ }
- if (!IT7260_i2cWriteNoReadyCheck(BUF_COMMAND, cmd_ident,
- sizeof(cmd_ident))) {
- dev_err(&gl_ts->client->dev, "failed to write CMD_IDENT_CHIP\n");
- return -ENODEV;
+ ret = it7260_i2c_write_no_ready_check(ts_data, BUF_COMMAND, cmd_ident,
+ sizeof(cmd_ident));
+ if (ret != IT_I2C_WRITE_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to write CMD_IDENT_CHIP %d\n", ret);
+ return ret;
+ }
+
+ /*
+ * Sometimes, the controller may not respond immediately after
+ * writing the command, so wait for device to get ready.
+ * TRUE means to retry 500 times at max to read the chip status.
+ * FALSE means to avoid unnecessary delays in each retry.
+ */
+ ret = it7260_wait_device_ready(ts_data, true, false);
+ if (ret < 0) {
+ dev_err(&ts_data->client->dev,
+ "failed to read chip status %d\n", ret);
+ return ret;
}
- IT7260_waitDeviceReady(false, false);
- if (!IT7260_i2cReadNoReadyCheck(BUF_RESPONSE, chip_id,
- sizeof(chip_id))) {
- dev_err(&gl_ts->client->dev, "failed to read chip-id\n");
- return -ENODEV;
+ ret = it7260_i2c_read_no_ready_check(ts_data, BUF_RESPONSE, chip_id,
+ sizeof(chip_id));
+ if (ret != IT_I2C_READ_RET) {
+ dev_err(&ts_data->client->dev,
+ "failed to read chip-id %d\n", ret);
+ return ret;
}
- dev_info(&gl_ts->client->dev,
- "IT7260_chipIdentify read id: %02X %c%c%c%c%c%c%c %c%c\n",
+ dev_info(&ts_data->client->dev,
+ "it7260_ts_chip_identify read id: %02X %c%c%c%c%c%c%c %c%c\n",
chip_id[0], chip_id[1], chip_id[2], chip_id[3], chip_id[4],
chip_id[5], chip_id[6], chip_id[7], chip_id[8], chip_id[9]);
@@ -1150,11 +1346,11 @@ static int IT7260_chipIdentify(void)
return -EINVAL;
if (chip_id[8] == '5' && chip_id[9] == '6')
- dev_info(&gl_ts->client->dev, "rev BX3 found\n");
+ dev_info(&ts_data->client->dev, "rev BX3 found\n");
else if (chip_id[8] == '6' && chip_id[9] == '6')
- dev_info(&gl_ts->client->dev, "rev BX4 found\n");
+ dev_info(&ts_data->client->dev, "rev BX4 found\n");
else
- dev_info(&gl_ts->client->dev, "unknown revision (0x%02X 0x%02X) found\n",
+ dev_info(&ts_data->client->dev, "unknown revision (0x%02X 0x%02X) found\n",
chip_id[8], chip_id[9]);
return 0;
@@ -1166,44 +1362,44 @@ static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
regulator_set_optimum_mode(reg, load_uA) : 0;
}
-static int IT7260_regulator_configure(bool on)
+static int it7260_regulator_configure(struct it7260_ts_data *ts_data, bool on)
{
int retval;
if (on == false)
goto hw_shutdown;
- gl_ts->vdd = devm_regulator_get(&gl_ts->client->dev, "vdd");
- if (IS_ERR(gl_ts->vdd)) {
- dev_err(&gl_ts->client->dev,
+ ts_data->vdd = devm_regulator_get(&ts_data->client->dev, "vdd");
+ if (IS_ERR(ts_data->vdd)) {
+ dev_err(&ts_data->client->dev,
"%s: Failed to get vdd regulator\n", __func__);
- return PTR_ERR(gl_ts->vdd);
+ return PTR_ERR(ts_data->vdd);
}
- if (regulator_count_voltages(gl_ts->vdd) > 0) {
- retval = regulator_set_voltage(gl_ts->vdd,
+ if (regulator_count_voltages(ts_data->vdd) > 0) {
+ retval = regulator_set_voltage(ts_data->vdd,
IT_VTG_MIN_UV, IT_VTG_MAX_UV);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"regulator set_vtg failed retval =%d\n",
retval);
goto err_set_vtg_vdd;
}
}
- gl_ts->avdd = devm_regulator_get(&gl_ts->client->dev, "avdd");
- if (IS_ERR(gl_ts->avdd)) {
- dev_err(&gl_ts->client->dev,
+ ts_data->avdd = devm_regulator_get(&ts_data->client->dev, "avdd");
+ if (IS_ERR(ts_data->avdd)) {
+ dev_err(&ts_data->client->dev,
"%s: Failed to get i2c regulator\n", __func__);
- retval = PTR_ERR(gl_ts->avdd);
+ retval = PTR_ERR(ts_data->avdd);
goto err_get_vtg_i2c;
}
- if (regulator_count_voltages(gl_ts->avdd) > 0) {
- retval = regulator_set_voltage(gl_ts->avdd,
+ if (regulator_count_voltages(ts_data->avdd) > 0) {
+ retval = regulator_set_voltage(ts_data->avdd,
IT_I2C_VTG_MIN_UV, IT_I2C_VTG_MAX_UV);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"reg set i2c vtg failed retval =%d\n",
retval);
goto err_set_vtg_i2c;
@@ -1214,55 +1410,55 @@ static int IT7260_regulator_configure(bool on)
err_set_vtg_i2c:
err_get_vtg_i2c:
- if (regulator_count_voltages(gl_ts->vdd) > 0)
- regulator_set_voltage(gl_ts->vdd, 0, IT_VTG_MAX_UV);
+ if (regulator_count_voltages(ts_data->vdd) > 0)
+ regulator_set_voltage(ts_data->vdd, 0, IT_VTG_MAX_UV);
err_set_vtg_vdd:
return retval;
hw_shutdown:
- if (regulator_count_voltages(gl_ts->vdd) > 0)
- regulator_set_voltage(gl_ts->vdd, 0, IT_VTG_MAX_UV);
- if (regulator_count_voltages(gl_ts->avdd) > 0)
- regulator_set_voltage(gl_ts->avdd, 0, IT_I2C_VTG_MAX_UV);
+ if (regulator_count_voltages(ts_data->vdd) > 0)
+ regulator_set_voltage(ts_data->vdd, 0, IT_VTG_MAX_UV);
+ if (regulator_count_voltages(ts_data->avdd) > 0)
+ regulator_set_voltage(ts_data->avdd, 0, IT_I2C_VTG_MAX_UV);
return 0;
};
-static int IT7260_power_on(bool on)
+static int it7260_power_on(struct it7260_ts_data *ts_data, bool on)
{
int retval;
if (on == false)
goto power_off;
- retval = reg_set_optimum_mode_check(gl_ts->vdd,
+ retval = reg_set_optimum_mode_check(ts_data->vdd,
IT_ACTIVE_LOAD_UA);
if (retval < 0) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"Regulator vdd set_opt failed rc=%d\n",
retval);
return retval;
}
- retval = regulator_enable(gl_ts->vdd);
+ retval = regulator_enable(ts_data->vdd);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"Regulator vdd enable failed rc=%d\n",
retval);
goto error_reg_en_vdd;
}
- retval = reg_set_optimum_mode_check(gl_ts->avdd,
+ retval = reg_set_optimum_mode_check(ts_data->avdd,
IT_I2C_ACTIVE_LOAD_UA);
if (retval < 0) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"Regulator avdd set_opt failed rc=%d\n",
retval);
goto error_reg_opt_i2c;
}
- retval = regulator_enable(gl_ts->avdd);
+ retval = regulator_enable(ts_data->avdd);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"Regulator avdd enable failed rc=%d\n",
retval);
goto error_reg_en_avdd;
@@ -1271,118 +1467,119 @@ static int IT7260_power_on(bool on)
return 0;
error_reg_en_avdd:
- reg_set_optimum_mode_check(gl_ts->avdd, 0);
+ reg_set_optimum_mode_check(ts_data->avdd, 0);
error_reg_opt_i2c:
- regulator_disable(gl_ts->vdd);
+ regulator_disable(ts_data->vdd);
error_reg_en_vdd:
- reg_set_optimum_mode_check(gl_ts->vdd, 0);
+ reg_set_optimum_mode_check(ts_data->vdd, 0);
return retval;
power_off:
- reg_set_optimum_mode_check(gl_ts->vdd, 0);
- regulator_disable(gl_ts->vdd);
- reg_set_optimum_mode_check(gl_ts->avdd, 0);
- regulator_disable(gl_ts->avdd);
+ reg_set_optimum_mode_check(ts_data->vdd, 0);
+ regulator_disable(ts_data->vdd);
+ reg_set_optimum_mode_check(ts_data->avdd, 0);
+ regulator_disable(ts_data->avdd);
return 0;
}
-static int IT7260_gpio_configure(bool on)
+static int it7260_gpio_configure(struct it7260_ts_data *ts_data, bool on)
{
int retval = 0;
if (on) {
- if (gpio_is_valid(gl_ts->pdata->irq_gpio)) {
+ if (gpio_is_valid(ts_data->pdata->irq_gpio)) {
/* configure touchscreen irq gpio */
- retval = gpio_request(gl_ts->pdata->irq_gpio,
+ retval = gpio_request(ts_data->pdata->irq_gpio,
"ite_irq_gpio");
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"unable to request irq gpio [%d]\n",
retval);
goto err_irq_gpio_req;
}
- retval = gpio_direction_input(gl_ts->pdata->irq_gpio);
+ retval = gpio_direction_input(ts_data->pdata->irq_gpio);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"unable to set direction for irq gpio [%d]\n",
retval);
goto err_irq_gpio_dir;
}
} else {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"irq gpio not provided\n");
goto err_irq_gpio_req;
}
- if (gpio_is_valid(gl_ts->pdata->reset_gpio)) {
+ if (gpio_is_valid(ts_data->pdata->reset_gpio)) {
/* configure touchscreen reset out gpio */
- retval = gpio_request(gl_ts->pdata->reset_gpio,
+ retval = gpio_request(ts_data->pdata->reset_gpio,
"ite_reset_gpio");
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"unable to request reset gpio [%d]\n",
retval);
goto err_reset_gpio_req;
}
retval = gpio_direction_output(
- gl_ts->pdata->reset_gpio, 1);
+ ts_data->pdata->reset_gpio, 1);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"unable to set direction for reset gpio [%d]\n",
retval);
goto err_reset_gpio_dir;
}
- if (gl_ts->pdata->low_reset)
- gpio_set_value(gl_ts->pdata->reset_gpio, 0);
+ if (ts_data->pdata->low_reset)
+ gpio_set_value(ts_data->pdata->reset_gpio, 0);
else
- gpio_set_value(gl_ts->pdata->reset_gpio, 1);
+ gpio_set_value(ts_data->pdata->reset_gpio, 1);
- msleep(gl_ts->pdata->reset_delay);
+ msleep(ts_data->pdata->reset_delay);
} else {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"reset gpio not provided\n");
goto err_reset_gpio_req;
}
} else {
- if (gpio_is_valid(gl_ts->pdata->irq_gpio))
- gpio_free(gl_ts->pdata->irq_gpio);
- if (gpio_is_valid(gl_ts->pdata->reset_gpio)) {
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
+ gpio_free(ts_data->pdata->irq_gpio);
+ if (gpio_is_valid(ts_data->pdata->reset_gpio)) {
/*
* This is intended to save leakage current
* only. Even if the call(gpio_direction_input)
* fails, only leakage current will be more but
* functionality will not be affected.
*/
- retval = gpio_direction_input(gl_ts->pdata->reset_gpio);
+ retval = gpio_direction_input(
+ ts_data->pdata->reset_gpio);
if (retval) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"unable to set direction for gpio reset [%d]\n",
retval);
}
- gpio_free(gl_ts->pdata->reset_gpio);
+ gpio_free(ts_data->pdata->reset_gpio);
}
}
return 0;
err_reset_gpio_dir:
- if (gpio_is_valid(gl_ts->pdata->reset_gpio))
- gpio_free(gl_ts->pdata->reset_gpio);
+ if (gpio_is_valid(ts_data->pdata->reset_gpio))
+ gpio_free(ts_data->pdata->reset_gpio);
err_reset_gpio_req:
err_irq_gpio_dir:
- if (gpio_is_valid(gl_ts->pdata->irq_gpio))
- gpio_free(gl_ts->pdata->irq_gpio);
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
+ gpio_free(ts_data->pdata->irq_gpio);
err_irq_gpio_req:
return retval;
}
#if CONFIG_OF
-static int IT7260_get_dt_coords(struct device *dev, char *name,
- struct IT7260_ts_platform_data *pdata)
+static int it7260_get_dt_coords(struct device *dev, char *name,
+ struct it7260_ts_platform_data *pdata)
{
u32 coords[IT7260_COORDS_ARR_SIZE];
struct property *prop;
@@ -1435,9 +1632,10 @@ static int IT7260_get_dt_coords(struct device *dev, char *name,
return 0;
}
-static int IT7260_parse_dt(struct device *dev,
- struct IT7260_ts_platform_data *pdata)
+static int it7260_parse_dt(struct device *dev,
+ struct it7260_ts_platform_data *pdata)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
struct device_node *np = dev->of_node;
u32 temp_val;
int rc;
@@ -1481,9 +1679,9 @@ static int IT7260_parse_dt(struct device *dev,
return rc;
}
- snprintf(gl_ts->fw_name, MAX_BUFFER_SIZE, "%s",
+ snprintf(ts_data->fw_name, MAX_BUFFER_SIZE, "%s",
(pdata->fw_name != NULL) ? pdata->fw_name : FW_NAME);
- snprintf(gl_ts->cfg_name, MAX_BUFFER_SIZE, "%s",
+ snprintf(ts_data->cfg_name, MAX_BUFFER_SIZE, "%s",
(pdata->cfg_name != NULL) ? pdata->cfg_name : CFG_NAME);
rc = of_property_read_u32(np, "ite,reset-delay", &temp_val);
@@ -1504,25 +1702,25 @@ static int IT7260_parse_dt(struct device *dev,
pdata->low_reset = of_property_read_bool(np, "ite,low-reset");
- rc = IT7260_get_dt_coords(dev, "ite,display-coords", pdata);
+ rc = it7260_get_dt_coords(dev, "ite,display-coords", pdata);
if (rc && (rc != -EINVAL))
return rc;
- rc = IT7260_get_dt_coords(dev, "ite,panel-coords", pdata);
+ rc = it7260_get_dt_coords(dev, "ite,panel-coords", pdata);
if (rc && (rc != -EINVAL))
return rc;
return 0;
}
#else
-static inline int IT7260_ts_parse_dt(struct device *dev,
- struct IT7260_ts_platform_data *pdata)
+static inline int it7260_ts_parse_dt(struct device *dev,
+ struct it7260_ts_platform_data *pdata)
{
return 0;
}
#endif
-static int IT7260_ts_pinctrl_init(struct IT7260_ts_data *ts_data)
+static int it7260_ts_pinctrl_init(struct it7260_ts_data *ts_data)
{
int retval;
@@ -1576,11 +1774,12 @@ err_pinctrl_get:
return retval;
}
-static int IT7260_ts_probe(struct i2c_client *client,
+static int it7260_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
static const uint8_t cmd_start[] = {CMD_UNKNOWN_7};
- struct IT7260_ts_platform_data *pdata;
+ struct it7260_ts_data *ts_data;
+ struct it7260_ts_platform_data *pdata;
uint8_t rsp[2];
int ret = -1, err;
struct dentry *temp;
@@ -1590,40 +1789,39 @@ static int IT7260_ts_probe(struct i2c_client *client,
return -ENODEV;
}
- gl_ts = devm_kzalloc(&client->dev, sizeof(*gl_ts), GFP_KERNEL);
- if (!gl_ts)
+ ts_data = devm_kzalloc(&client->dev, sizeof(*ts_data), GFP_KERNEL);
+ if (!ts_data)
return -ENOMEM;
- gl_ts->client = client;
- i2c_set_clientdata(client, gl_ts);
-
- if (client->dev.platform_data == NULL)
- return -ENODEV;
+ ts_data->client = client;
+ i2c_set_clientdata(client, ts_data);
if (client->dev.of_node) {
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
- ret = IT7260_parse_dt(&client->dev, pdata);
+ ret = it7260_parse_dt(&client->dev, pdata);
if (ret)
return ret;
} else {
pdata = client->dev.platform_data;
}
- if (!pdata)
+ if (!pdata) {
+ dev_err(&client->dev, "No platform data found\n");
return -ENOMEM;
+ }
- gl_ts->pdata = pdata;
+ ts_data->pdata = pdata;
- ret = IT7260_regulator_configure(true);
+ ret = it7260_regulator_configure(ts_data, true);
if (ret < 0) {
dev_err(&client->dev, "Failed to configure regulators\n");
goto err_reg_configure;
}
- ret = IT7260_power_on(true);
+ ret = it7260_power_on(ts_data, true);
if (ret < 0) {
dev_err(&client->dev, "Failed to power on\n");
goto err_power_device;
@@ -1635,81 +1833,82 @@ static int IT7260_ts_probe(struct i2c_client *client,
*/
msleep(DELAY_VTG_REG_EN);
- ret = IT7260_ts_pinctrl_init(gl_ts);
- if (!ret && gl_ts->ts_pinctrl) {
+ ret = it7260_ts_pinctrl_init(ts_data);
+ if (!ret && ts_data->ts_pinctrl) {
/*
* Pinctrl handle is optional. If pinctrl handle is found
* let pins to be configured in active state. If not
* found continue further without error.
*/
- ret = pinctrl_select_state(gl_ts->ts_pinctrl,
- gl_ts->pinctrl_state_active);
+ ret = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_active);
if (ret < 0) {
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"failed to select pin to active state %d",
ret);
}
} else {
- ret = IT7260_gpio_configure(true);
+ ret = it7260_gpio_configure(ts_data, true);
if (ret < 0) {
dev_err(&client->dev, "Failed to configure gpios\n");
goto err_gpio_config;
}
}
- ret = IT7260_chipIdentify();
+ ret = it7260_ts_chip_identify(ts_data);
if (ret) {
dev_err(&client->dev, "Failed to identify chip %d!!!", ret);
goto err_identification_fail;
}
- IT7260_get_chip_versions(&client->dev);
+ it7260_get_chip_versions(ts_data);
- gl_ts->input_dev = input_allocate_device();
- if (!gl_ts->input_dev) {
+ ts_data->input_dev = input_allocate_device();
+ if (!ts_data->input_dev) {
dev_err(&client->dev, "failed to allocate input device\n");
ret = -ENOMEM;
goto err_input_alloc;
}
/* Initialize mutex for fw and cfg upgrade */
- mutex_init(&gl_ts->fw_cfg_mutex);
-
- gl_ts->input_dev->name = DEVICE_NAME;
- gl_ts->input_dev->phys = "I2C";
- gl_ts->input_dev->id.bustype = BUS_I2C;
- gl_ts->input_dev->id.vendor = 0x0001;
- gl_ts->input_dev->id.product = 0x7260;
- set_bit(EV_SYN, gl_ts->input_dev->evbit);
- set_bit(EV_KEY, gl_ts->input_dev->evbit);
- set_bit(EV_ABS, gl_ts->input_dev->evbit);
- set_bit(INPUT_PROP_DIRECT, gl_ts->input_dev->propbit);
- set_bit(BTN_TOUCH, gl_ts->input_dev->keybit);
- input_set_abs_params(gl_ts->input_dev, ABS_MT_POSITION_X,
- gl_ts->pdata->disp_minx, gl_ts->pdata->disp_maxx, 0, 0);
- input_set_abs_params(gl_ts->input_dev, ABS_MT_POSITION_Y,
- gl_ts->pdata->disp_miny, gl_ts->pdata->disp_maxy, 0, 0);
- input_mt_init_slots(gl_ts->input_dev, gl_ts->pdata->num_of_fingers, 0);
-
- input_set_drvdata(gl_ts->input_dev, gl_ts);
+ mutex_init(&ts_data->fw_cfg_mutex);
+
+ ts_data->input_dev->name = DEVICE_NAME;
+ ts_data->input_dev->phys = "I2C";
+ ts_data->input_dev->id.bustype = BUS_I2C;
+ ts_data->input_dev->id.vendor = 0x0001;
+ ts_data->input_dev->id.product = 0x7260;
+ set_bit(EV_SYN, ts_data->input_dev->evbit);
+ set_bit(EV_KEY, ts_data->input_dev->evbit);
+ set_bit(EV_ABS, ts_data->input_dev->evbit);
+ set_bit(INPUT_PROP_DIRECT, ts_data->input_dev->propbit);
+ set_bit(BTN_TOUCH, ts_data->input_dev->keybit);
+ input_set_abs_params(ts_data->input_dev, ABS_MT_POSITION_X,
+ ts_data->pdata->disp_minx, ts_data->pdata->disp_maxx, 0, 0);
+ input_set_abs_params(ts_data->input_dev, ABS_MT_POSITION_Y,
+ ts_data->pdata->disp_miny, ts_data->pdata->disp_maxy, 0, 0);
+ input_mt_init_slots(ts_data->input_dev,
+ ts_data->pdata->num_of_fingers, 0);
+
+ input_set_drvdata(ts_data->input_dev, ts_data);
if (pdata->wakeup) {
- set_bit(KEY_WAKEUP, gl_ts->input_dev->keybit);
- INIT_WORK(&gl_ts->work_pm_relax, IT7260_ts_work_func);
+ set_bit(KEY_WAKEUP, ts_data->input_dev->keybit);
+ INIT_WORK(&ts_data->work_pm_relax, it7260_ts_work_func);
device_init_wakeup(&client->dev, pdata->wakeup);
}
if (pdata->palm_detect_en)
- set_bit(gl_ts->pdata->palm_detect_keycode,
- gl_ts->input_dev->keybit);
+ set_bit(ts_data->pdata->palm_detect_keycode,
+ ts_data->input_dev->keybit);
- if (input_register_device(gl_ts->input_dev)) {
+ if (input_register_device(ts_data->input_dev)) {
dev_err(&client->dev, "failed to register input device\n");
goto err_input_register;
}
- if (request_threaded_irq(client->irq, NULL, IT7260_ts_threaded_handler,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, gl_ts)) {
+ if (request_threaded_irq(client->irq, NULL, it7260_ts_threaded_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, ts_data)) {
dev_err(&client->dev, "request_irq failed\n");
goto err_irq_reg;
}
@@ -1720,30 +1919,31 @@ static int IT7260_ts_probe(struct i2c_client *client,
}
#if defined(CONFIG_FB)
- gl_ts->fb_notif.notifier_call = fb_notifier_callback;
+ ts_data->fb_notif.notifier_call = fb_notifier_callback;
- ret = fb_register_client(&gl_ts->fb_notif);
+ ret = fb_register_client(&ts_data->fb_notif);
if (ret)
dev_err(&client->dev, "Unable to register fb_notifier %d\n",
ret);
#endif
- IT7260_i2cWriteNoReadyCheck(BUF_COMMAND, cmd_start, sizeof(cmd_start));
+ it7260_i2c_write_no_ready_check(ts_data, BUF_COMMAND, cmd_start,
+ sizeof(cmd_start));
msleep(pdata->reset_delay);
- IT7260_i2cReadNoReadyCheck(BUF_RESPONSE, rsp, sizeof(rsp));
+ it7260_i2c_read_no_ready_check(ts_data, BUF_RESPONSE, rsp, sizeof(rsp));
msleep(pdata->reset_delay);
- gl_ts->dir = debugfs_create_dir(DEBUGFS_DIR_NAME, NULL);
- if (gl_ts->dir == NULL || IS_ERR(gl_ts->dir)) {
+ ts_data->dir = debugfs_create_dir(DEBUGFS_DIR_NAME, NULL);
+ if (ts_data->dir == NULL || IS_ERR(ts_data->dir)) {
dev_err(&client->dev,
"%s: Failed to create debugfs directory, ret = %ld\n",
- __func__, PTR_ERR(gl_ts->dir));
- ret = PTR_ERR(gl_ts->dir);
+ __func__, PTR_ERR(ts_data->dir));
+ ret = PTR_ERR(ts_data->dir);
goto err_create_debugfs_dir;
}
- temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, gl_ts->dir,
- gl_ts, &debug_suspend_fops);
+ temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, ts_data->dir,
+ ts_data, &debug_suspend_fops);
if (temp == NULL || IS_ERR(temp)) {
dev_err(&client->dev,
"%s: Failed to create suspend debugfs file, ret = %ld\n",
@@ -1755,40 +1955,40 @@ static int IT7260_ts_probe(struct i2c_client *client,
return 0;
err_create_debugfs_file:
- debugfs_remove_recursive(gl_ts->dir);
+ debugfs_remove_recursive(ts_data->dir);
err_create_debugfs_dir:
#if defined(CONFIG_FB)
- if (fb_unregister_client(&gl_ts->fb_notif))
+ if (fb_unregister_client(&ts_data->fb_notif))
dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
#endif
sysfs_remove_group(&(client->dev.kobj), &it7260_attr_group);
err_sysfs_grp_create:
- free_irq(client->irq, gl_ts);
+ free_irq(client->irq, ts_data);
err_irq_reg:
- input_unregister_device(gl_ts->input_dev);
+ input_unregister_device(ts_data->input_dev);
err_input_register:
if (pdata->wakeup) {
- cancel_work_sync(&gl_ts->work_pm_relax);
+ cancel_work_sync(&ts_data->work_pm_relax);
device_init_wakeup(&client->dev, false);
}
- if (gl_ts->input_dev)
- input_free_device(gl_ts->input_dev);
- gl_ts->input_dev = NULL;
+ if (ts_data->input_dev)
+ input_free_device(ts_data->input_dev);
+ ts_data->input_dev = NULL;
err_input_alloc:
err_identification_fail:
- if (gl_ts->ts_pinctrl) {
- if (IS_ERR_OR_NULL(gl_ts->pinctrl_state_release)) {
- devm_pinctrl_put(gl_ts->ts_pinctrl);
- gl_ts->ts_pinctrl = NULL;
+ if (ts_data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+ ts_data->ts_pinctrl = NULL;
} else {
- err = pinctrl_select_state(gl_ts->ts_pinctrl,
- gl_ts->pinctrl_state_release);
+ err = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_release);
if (err)
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"failed to select relase pinctrl state %d\n",
err);
}
@@ -1800,54 +2000,55 @@ err_identification_fail:
}
err_gpio_config:
- IT7260_power_on(false);
+ it7260_power_on(ts_data, false);
err_power_device:
- IT7260_regulator_configure(false);
+ it7260_regulator_configure(ts_data, false);
err_reg_configure:
return ret;
}
-static int IT7260_ts_remove(struct i2c_client *client)
+static int it7260_ts_remove(struct i2c_client *client)
{
+ struct it7260_ts_data *ts_data = i2c_get_clientdata(client);
int ret;
- debugfs_remove_recursive(gl_ts->dir);
+ debugfs_remove_recursive(ts_data->dir);
#if defined(CONFIG_FB)
- if (fb_unregister_client(&gl_ts->fb_notif))
+ if (fb_unregister_client(&ts_data->fb_notif))
dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
#endif
sysfs_remove_group(&(client->dev.kobj), &it7260_attr_group);
- free_irq(client->irq, gl_ts);
- input_unregister_device(gl_ts->input_dev);
- if (gl_ts->input_dev)
- input_free_device(gl_ts->input_dev);
- gl_ts->input_dev = NULL;
- if (gl_ts->pdata->wakeup) {
- cancel_work_sync(&gl_ts->work_pm_relax);
+ free_irq(client->irq, ts_data);
+ input_unregister_device(ts_data->input_dev);
+ if (ts_data->input_dev)
+ input_free_device(ts_data->input_dev);
+ ts_data->input_dev = NULL;
+ if (ts_data->pdata->wakeup) {
+ cancel_work_sync(&ts_data->work_pm_relax);
device_init_wakeup(&client->dev, false);
}
- if (gl_ts->ts_pinctrl) {
- if (IS_ERR_OR_NULL(gl_ts->pinctrl_state_release)) {
- devm_pinctrl_put(gl_ts->ts_pinctrl);
- gl_ts->ts_pinctrl = NULL;
+ if (ts_data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+ ts_data->ts_pinctrl = NULL;
} else {
- ret = pinctrl_select_state(gl_ts->ts_pinctrl,
- gl_ts->pinctrl_state_release);
+ ret = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_release);
if (ret)
- dev_err(&gl_ts->client->dev,
+ dev_err(&ts_data->client->dev,
"failed to select relase pinctrl state %d\n",
ret);
}
} else {
- if (gpio_is_valid(gl_ts->pdata->reset_gpio))
- gpio_free(gl_ts->pdata->reset_gpio);
- if (gpio_is_valid(gl_ts->pdata->irq_gpio))
- gpio_free(gl_ts->pdata->irq_gpio);
+ if (gpio_is_valid(ts_data->pdata->reset_gpio))
+ gpio_free(ts_data->pdata->reset_gpio);
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
+ gpio_free(ts_data->pdata->irq_gpio);
}
- IT7260_power_on(false);
- IT7260_regulator_configure(false);
+ it7260_power_on(ts_data, false);
+ it7260_regulator_configure(ts_data, false);
return 0;
}
@@ -1856,17 +2057,19 @@ static int IT7260_ts_remove(struct i2c_client *client)
static int fb_notifier_callback(struct notifier_block *self,
unsigned long event, void *data)
{
+ struct it7260_ts_data *ts_data = container_of(self,
+ struct it7260_ts_data, fb_notif);
struct fb_event *evdata = data;
int *blank;
- if (evdata && evdata->data && gl_ts && gl_ts->client) {
+ if (evdata && evdata->data && ts_data && ts_data->client) {
if (event == FB_EVENT_BLANK) {
blank = evdata->data;
if (*blank == FB_BLANK_UNBLANK)
- IT7260_ts_resume(&(gl_ts->client->dev));
+ it7260_ts_resume(&(ts_data->client->dev));
else if (*blank == FB_BLANK_POWERDOWN ||
*blank == FB_BLANK_VSYNC_SUSPEND)
- IT7260_ts_suspend(&(gl_ts->client->dev));
+ it7260_ts_suspend(&(ts_data->client->dev));
}
}
@@ -1875,30 +2078,32 @@ static int fb_notifier_callback(struct notifier_block *self,
#endif
#ifdef CONFIG_PM
-static int IT7260_ts_resume(struct device *dev)
+static int it7260_ts_resume(struct device *dev)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int retval;
if (device_may_wakeup(dev)) {
- if (gl_ts->device_needs_wakeup) {
+ if (ts_data->device_needs_wakeup) {
/* Set active current for the avdd regulator */
- if (gl_ts->pdata->avdd_lpm_cur) {
- retval = reg_set_optimum_mode_check(gl_ts->avdd,
+ if (ts_data->pdata->avdd_lpm_cur) {
+ retval = reg_set_optimum_mode_check(
+ ts_data->avdd,
IT_I2C_ACTIVE_LOAD_UA);
if (retval < 0)
dev_err(dev, "Regulator avdd set_opt failed at resume rc=%d\n",
retval);
}
- gl_ts->device_needs_wakeup = false;
- disable_irq_wake(gl_ts->client->irq);
+ ts_data->device_needs_wakeup = false;
+ disable_irq_wake(ts_data->client->irq);
}
return 0;
}
- if (gl_ts->ts_pinctrl) {
- retval = pinctrl_select_state(gl_ts->ts_pinctrl,
- gl_ts->pinctrl_state_active);
+ if (ts_data->ts_pinctrl) {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_active);
if (retval < 0) {
dev_err(dev, "Cannot get default pinctrl state %d\n",
retval);
@@ -1906,50 +2111,53 @@ static int IT7260_ts_resume(struct device *dev)
}
}
- enable_irq(gl_ts->client->irq);
- gl_ts->suspended = false;
+ enable_irq(ts_data->client->irq);
+ ts_data->suspended = false;
return 0;
err_pinctrl_select_suspend:
return retval;
}
-static int IT7260_ts_suspend(struct device *dev)
+static int it7260_ts_suspend(struct device *dev)
{
+ struct it7260_ts_data *ts_data = dev_get_drvdata(dev);
int retval;
- if (gl_ts->fw_cfg_uploading) {
+ if (ts_data->fw_cfg_uploading) {
dev_dbg(dev, "Fw/cfg uploading. Can't go to suspend.\n");
return -EBUSY;
}
if (device_may_wakeup(dev)) {
- if (!gl_ts->device_needs_wakeup) {
+ if (!ts_data->device_needs_wakeup) {
/* put the device in low power idle mode */
- IT7260_ts_chipLowPowerMode(PWR_CTL_LOW_POWER_MODE);
+ it7260_ts_chip_low_power_mode(ts_data,
+ PWR_CTL_LOW_POWER_MODE);
/* Set lpm current for avdd regulator */
- if (gl_ts->pdata->avdd_lpm_cur) {
- retval = reg_set_optimum_mode_check(gl_ts->avdd,
- gl_ts->pdata->avdd_lpm_cur);
+ if (ts_data->pdata->avdd_lpm_cur) {
+ retval = reg_set_optimum_mode_check(
+ ts_data->avdd,
+ ts_data->pdata->avdd_lpm_cur);
if (retval < 0)
dev_err(dev, "Regulator avdd set_opt failed at suspend rc=%d\n",
retval);
}
- gl_ts->device_needs_wakeup = true;
- enable_irq_wake(gl_ts->client->irq);
+ ts_data->device_needs_wakeup = true;
+ enable_irq_wake(ts_data->client->irq);
}
return 0;
}
- disable_irq(gl_ts->client->irq);
+ disable_irq(ts_data->client->irq);
- IT7260_ts_release_all();
+ it7260_ts_release_all(ts_data);
- if (gl_ts->ts_pinctrl) {
- retval = pinctrl_select_state(gl_ts->ts_pinctrl,
- gl_ts->pinctrl_state_suspend);
+ if (ts_data->ts_pinctrl) {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_suspend);
if (retval < 0) {
dev_err(dev, "Cannot get idle pinctrl state %d\n",
retval);
@@ -1957,7 +2165,7 @@ static int IT7260_ts_suspend(struct device *dev)
}
}
- gl_ts->suspended = true;
+ ts_data->suspended = true;
return 0;
@@ -1965,49 +2173,49 @@ err_pinctrl_select_suspend:
return retval;
}
-static const struct dev_pm_ops IT7260_ts_dev_pm_ops = {
- .suspend = IT7260_ts_suspend,
- .resume = IT7260_ts_resume,
+static const struct dev_pm_ops it7260_ts_dev_pm_ops = {
+ .suspend = it7260_ts_suspend,
+ .resume = it7260_ts_resume,
};
#else
-static int IT7260_ts_resume(struct device *dev)
+static int it7260_ts_resume(struct device *dev)
{
return 0;
}
-static int IT7260_ts_suspend(struct device *dev)
+static int it7260_ts_suspend(struct device *dev)
{
return 0;
}
#endif
-static const struct i2c_device_id IT7260_ts_id[] = {
+static const struct i2c_device_id it7260_ts_id[] = {
{ DEVICE_NAME, 0},
{}
};
-MODULE_DEVICE_TABLE(i2c, IT7260_ts_id);
+MODULE_DEVICE_TABLE(i2c, it7260_ts_id);
-static const struct of_device_id IT7260_match_table[] = {
+static const struct of_device_id it7260_match_table[] = {
{ .compatible = "ite,it7260_ts",},
{},
};
-static struct i2c_driver IT7260_ts_driver = {
+static struct i2c_driver it7260_ts_driver = {
.driver = {
.owner = THIS_MODULE,
.name = DEVICE_NAME,
- .of_match_table = IT7260_match_table,
+ .of_match_table = it7260_match_table,
#ifdef CONFIG_PM
- .pm = &IT7260_ts_dev_pm_ops,
+ .pm = &it7260_ts_dev_pm_ops,
#endif
},
- .probe = IT7260_ts_probe,
- .remove = IT7260_ts_remove,
- .id_table = IT7260_ts_id,
+ .probe = it7260_ts_probe,
+ .remove = it7260_ts_remove,
+ .id_table = it7260_ts_id,
};
-module_i2c_driver(IT7260_ts_driver);
+module_i2c_driver(it7260_ts_driver);
-MODULE_DESCRIPTION("IT7260 Touchscreen Driver");
+MODULE_DESCRIPTION("it7260 Touchscreen Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/msg21xx_ts.c b/drivers/input/touchscreen/msg21xx_ts.c
index 4eb7fd4b1cc9..8f2c4da578fc 100644
--- a/drivers/input/touchscreen/msg21xx_ts.c
+++ b/drivers/input/touchscreen/msg21xx_ts.c
@@ -5,6 +5,8 @@
*
* Copyright (C) 2012 Bruce Ding <bruce.ding@mstarsemi.com>
*
+ * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -17,72 +19,55 @@
*/
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/input.h>
+#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
-#include <linux/timer.h>
#include <linux/gpio.h>
-
+#include <linux/of_gpio.h>
#include <linux/sysfs.h>
#include <linux/init.h>
#include <linux/mutex.h>
-#include <mach/gpio.h>
-#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/slab.h>
-
-#include <linux/syscalls.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/fcntl.h>
+#include <linux/firmware.h>
#include <linux/string.h>
-#include <asm/unistd.h>
-#include <linux/cdev.h>
-#include <asm/uaccess.h>
-#if defined(CONFIG_HAS_EARLYSUSPEND)
-#include <linux/earlysuspend.h>
-#endif
-#include <linux/input.h>
+#include <linux/kthread.h>
+#include <linux/regulator/consumer.h>
+
#if defined(CONFIG_FB)
#include <linux/notifier.h>
#include <linux/fb.h>
#endif
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
+#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
#include <linux/input/vir_ps.h>
#endif
-/*=============================================================*/
-// Macro Definition
-/*=============================================================*/
+/* Macro Definition */
#define TOUCH_DRIVER_DEBUG 0
#if (TOUCH_DRIVER_DEBUG == 1)
-#define DBG(fmt, arg...) pr_err(fmt, ##arg) //pr_info(fmt, ##arg)
+#define DBG(fmt, arg...) pr_info(fmt, ##arg)
#else
#define DBG(fmt, arg...)
#endif
-/*=============================================================*/
-// Constant Value & Variable Definition
-/*=============================================================*/
+/* Constant Value & Variable Definition */
-#define U8 unsigned char
-#define U16 unsigned short
-#define U32 unsigned int
-#define S8 signed char
-#define S16 signed short
-#define S32 signed int
+#define MSTAR_VTG_MIN_UV 2800000
+#define MSTAR_VTG_MAX_UV 3300000
+#define MSTAR_I2C_VTG_MIN_UV 1800000
+#define MSTAR_I2C_VTG_MAX_UV 1800000
+
+#define MAX_BUTTONS 4
+#define FT_COORDS_ARR_SIZE 4
+#define MSTAR_FW_NAME_MAX_LEN 50
+
+#define MSTAR_CHIPTOP_REGISTER_BANK 0x1E
+#define MSTAR_CHIPTOP_REGISTER_ICTYPE 0xCC
+#define MSTAR_INIT_SW_ID 0x7FF
-#define TOUCH_SCREEN_X_MIN (0)
-#define TOUCH_SCREEN_Y_MIN (0)
-/*
- * Note.
- * Please change the below touch screen resolution according to the touch panel that you are using.
- */
-#define TOUCH_SCREEN_X_MAX (480)
-#define TOUCH_SCREEN_Y_MAX (800)
/*
* Note.
* Please do not change the below setting.
@@ -90,62 +75,29 @@
#define TPD_WIDTH (2048)
#define TPD_HEIGHT (2048)
-/*
- * Note.
- * Please change the below GPIO pin setting to follow the platform that you are using
- */
-static int int_gpio = 1;
-static int reset_gpio = 0;
-#define MS_TS_MSG21XX_GPIO_RST reset_gpio
-#define MS_TS_MSG21XX_GPIO_INT int_gpio
-//---------------------------------------------------------------------//
-
-//#define SYSFS_AUTHORITY_CHANGE_FOR_CTS_TEST
-
-#ifdef SYSFS_AUTHORITY_CHANGE_FOR_CTS_TEST
-#define SYSFS_AUTHORITY (0644)
-#else
-#define SYSFS_AUTHORITY (0777)
-#endif
-
-#define FIRMWARE_AUTOUPDATE
#ifdef FIRMWARE_AUTOUPDATE
-typedef enum {
- SWID_START = 1,
- SWID_TRULY = SWID_START,
- SWID_NULL,
-} SWID_ENUM;
+enum {
+ SWID_START = 1,
+ SWID_TRULY = SWID_START,
+ SWID_NULL,
+};
-unsigned char MSG_FIRMWARE[1][33*1024] =
-{
- {
- #include "msg21xx_truly_update_bin.h"
- }
+static unsigned char MSG_FIRMWARE[1][33*1024] = { {
+ #include "msg21xx_truly_update_bin.h"
+ }
};
#endif
#define CONFIG_TP_HAVE_KEY
-/*
- * Note.
- * If the below virtual key value definition are not consistent with those that defined in key layout file of platform,
- * please change the below virtual key value to follow the platform that you are using.
- */
-#ifdef CONFIG_TP_HAVE_KEY
-#define TOUCH_KEY_MENU (139) //229
-#define TOUCH_KEY_HOME (172) //102
-#define TOUCH_KEY_BACK (158)
-#define TOUCH_KEY_SEARCH (217)
-
-const U16 tp_key_array[] = {TOUCH_KEY_MENU, TOUCH_KEY_HOME, TOUCH_KEY_BACK, TOUCH_KEY_SEARCH};
-#define MAX_KEY_NUM (sizeof(tp_key_array)/sizeof(tp_key_array[0]))
-#endif
+#define PINCTRL_STATE_ACTIVE "pmx_ts_active"
+#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend"
+#define PINCTRL_STATE_RELEASE "pmx_ts_release"
-#define SLAVE_I2C_ID_DBBUS (0xC4>>1)
-#define SLAVE_I2C_ID_DWI2C (0x4C>>1)
+#define SLAVE_I2C_ID_DBBUS (0xC4>>1)
-#define DEMO_MODE_PACKET_LENGTH (8)
-#define MAX_TOUCH_NUM (2) //5
+#define DEMO_MODE_PACKET_LENGTH (8)
+#define MAX_TOUCH_NUM (2)
#define TP_PRINT
#ifdef TP_PRINT
@@ -153,1605 +105,2089 @@ static int tp_print_proc_read(void);
static void tp_print_create_entry(void);
#endif
-static char *fw_version = NULL; // customer firmware version
-static U16 fw_version_major = 0;
-static U16 fw_version_minor = 0;
-static U8 temp[94][1024];
-static U32 crc32_table[256];
-static int FwDataCnt = 0;
-static U8 bFwUpdating = 0;
-static struct class *firmware_class = NULL;
-static struct device *firmware_cmd_dev = NULL;
+static char *fw_version; /* customer firmware version */
+static unsigned short fw_version_major;
+static unsigned short fw_version_minor;
+static unsigned char temp[94][1024];
+static unsigned int crc32_table[256];
+static int FwDataCnt;
+static unsigned char bFwUpdating;
+static struct class *firmware_class;
+static struct device *firmware_cmd_dev;
+
+static struct i2c_client *i2c_client;
+
+static u32 button_map[MAX_BUTTONS];
+static u32 num_buttons;
+
+static unsigned short update_bin_major, update_bin_minor;
+static unsigned short main_sw_id = MSTAR_INIT_SW_ID;
+static unsigned short info_sw_id = MSTAR_INIT_SW_ID;
+static unsigned int bin_conf_crc32;
+
+struct msg21xx_ts_platform_data {
+ const char *name;
+ char fw_name[MSTAR_FW_NAME_MAX_LEN];
+ char *fw_version;
+ unsigned short fw_version_major;
+ unsigned short fw_version_minor;
+ u32 irqflags;
+ u32 irq_gpio;
+ u32 irq_gpio_flags;
+ u32 reset_gpio;
+ u32 reset_gpio_flags;
+ u32 family_id;
+ u32 x_max;
+ u32 y_max;
+ u32 x_min;
+ u32 y_min;
+ u32 panel_minx;
+ u32 panel_miny;
+ u32 panel_maxx;
+ u32 panel_maxy;
+ u32 num_max_touches;
+ bool no_force_update;
+ bool i2c_pull_up;
+ bool ignore_id_check;
+ int (*power_init)(bool);
+ int (*power_on)(bool);
+ int (*power_init)(bool);
+ int (*power_on)(bool);
+};
-static struct i2c_client *i2c_client = NULL;
+static struct msg21xx_ts_platform_data *pdata;
+
+struct msg21xx_ts_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ const struct msg21xx_ts_platform_data *pdata;
+ struct regulator *vdd;
+ struct regulator *vcc_i2c;
+ bool loading_fw;
+ u8 family_id;
+ struct dentry *dir;
+ u16 addr;
+ bool suspended;
+ char *ts_info;
+ u8 *tch_data;
+ u32 tch_data_len;
+ u8 fw_ver[3];
+ u8 fw_vendor_id;
+#if defined(CONFIG_FB)
+ struct notifier_block fb_notif;
+#endif
+ struct pinctrl *ts_pinctrl;
+ struct pinctrl_state *pinctrl_state_active;
+ struct pinctrl_state *pinctrl_state_suspend;
+ struct pinctrl_state *pinctrl_state_release;
+ struct mutex ts_mutex;
+};
+
+static struct msg21xx_ts_data *ts_data;
#if defined(CONFIG_FB)
-static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data);
-static struct notifier_block msg21xx_fb_notif;
-#elif defined (CONFIG_HAS_EARLYSUSPEND)
-static struct early_suspend mstar_ts_early_suspend;
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data);
#endif
#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
-static U8 bEnableTpProximity = 0;
-static U8 bFaceClosingTp = 0;
+static unsigned char bEnableTpProximity;
+static unsigned char bFaceClosingTp;
#endif
-static U8 bTpInSuspend = 0;
-static int irq_msg21xx = -1;
-static struct work_struct msg21xx_wk;
static struct mutex msg21xx_mutex;
-static struct input_dev *input_dev = NULL;
+static struct input_dev *input_dev;
-/*=============================================================*/
-// Data Type Definition
-/*=============================================================*/
-typedef struct
-{
- U16 x;
- U16 y;
-} touchPoint_t;
+/* Data Type Definition */
-/// max 80+1+1 = 82 bytes
-typedef struct
-{
- touchPoint_t point[MAX_TOUCH_NUM];
- U8 count;
- U8 keycode;
-} touchInfo_t;
+struct touchPoint_t {
+ unsigned short x;
+ unsigned short y;
+};
-enum i2c_speed
-{
- I2C_SLOW = 0,
- I2C_NORMAL = 1, /* Enable erasing/writing for 10 msec. */
- I2C_FAST = 2, /* Disable EWENB before 10 msec timeout. */
+struct touchInfo_t {
+ struct touchPoint_t point[MAX_TOUCH_NUM];
+ unsigned char count;
+ unsigned char keycode;
};
-typedef enum
-{
- EMEM_ALL = 0,
- EMEM_MAIN,
- EMEM_INFO,
-} EMEM_TYPE_t;
-/*=============================================================*/
-// Function Definition
-/*=============================================================*/
+enum EMEM_TYPE_t {
+ EMEM_ALL = 0,
+ EMEM_MAIN,
+ EMEM_INFO,
+};
+
+/* Function Definition */
-/// CRC
-static U32 _CRC_doReflect(U32 ref, S8 ch)
+static unsigned int _CRC_doReflect(unsigned int ref, signed char ch)
{
- U32 value = 0;
- U32 i = 0;
-
- for (i = 1; i < (ch + 1); i ++)
- {
- if (ref & 1)
- {
- value |= 1 << (ch - i);
- }
- ref >>= 1;
- }
-
- return value;
+ unsigned int value = 0;
+ unsigned int i = 0;
+
+ for (i = 1; i < (ch + 1); i++) {
+ if (ref & 1)
+ value |= 1 << (ch - i);
+ ref >>= 1;
+ }
+
+ return value;
}
-U32 _CRC_getValue(U32 text, U32 prevCRC)
+static unsigned int _CRC_getValue(unsigned int text, unsigned int prevCRC)
{
- U32 ulCRC = prevCRC;
+ unsigned int ulCRC = prevCRC;
- ulCRC = (ulCRC >> 8) ^ crc32_table[(ulCRC & 0xFF) ^ text];
+ ulCRC = (ulCRC >> 8) ^ crc32_table[(ulCRC & 0xFF) ^ text];
- return ulCRC;
+ return ulCRC;
}
static void _CRC_initTable(void)
{
- U32 magic_number = 0x04c11db7;
- U32 i, j;
-
- for (i = 0; i <= 0xFF; i ++)
- {
- crc32_table[i] = _CRC_doReflect (i, 8) << 24;
- for (j = 0; j < 8; j ++)
- {
- crc32_table[i] = (crc32_table[i] << 1) ^ (crc32_table[i] & (0x80000000L) ? magic_number : 0);
- }
- crc32_table[i] = _CRC_doReflect(crc32_table[i], 32);
- }
+ unsigned int magic_number = 0x04c11db7;
+ unsigned int i, j;
+
+ for (i = 0; i <= 0xFF; i++) {
+ crc32_table[i] = _CRC_doReflect(i, 8) << 24;
+ for (j = 0; j < 8; j++)
+ crc32_table[i] = (crc32_table[i] << 1) ^
+ (crc32_table[i] & (0x80000000L) ?
+ magic_number : 0);
+ crc32_table[i] = _CRC_doReflect(crc32_table[i], 32);
+ }
}
static void reset_hw(void)
{
- DBG("reset_hw()\n");
-
- gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- mdelay(100); /* Note that the RST must be in LOW 10ms at least */
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(100); /* Enable the interrupt service thread/routine for INT after 50ms */
+ DBG("reset_hw()\n");
+
+ gpio_direction_output(pdata->reset_gpio, 1);
+ gpio_set_value_cansleep(pdata->reset_gpio, 0);
+ msleep(100); /* Note that the RST must be in LOW 10ms at least */
+ gpio_set_value_cansleep(pdata->reset_gpio, 1);
+ /* Enable the interrupt service thread/routine for INT after 50ms */
+ msleep(100);
}
-static int read_i2c_seq(U8 addr, U8* buf, U16 size)
+static int read_i2c_seq(unsigned char addr, unsigned char *buf,
+ unsigned short size)
{
- int rc = 0;
- struct i2c_msg msgs[] =
- {
- {
- .addr = addr,
- .flags = I2C_M_RD, // read flag
- .len = size,
- .buf = buf,
- },
- };
-
- /* If everything went ok (i.e. 1 msg transmitted), return #bytes
- transmitted, else error code. */
- if (i2c_client != NULL)
- {
- rc = i2c_transfer(i2c_client->adapter, msgs, 1);
- if (rc < 0)
- {
- DBG("read_i2c_seq() error %d\n", rc);
- }
- }
- else
- {
- DBG("i2c_client is NULL\n");
- }
-
- return rc;
+ int rc = 0;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = addr,
+ .flags = I2C_M_RD, /* read flag*/
+ .len = size,
+ .buf = buf,
+ },
+ };
+
+ /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+ * transmitted, else error code.
+ */
+ if (i2c_client != NULL) {
+ rc = i2c_transfer(i2c_client->adapter, msgs, 1);
+ if (rc < 0)
+ DBG("read_i2c_seq() error %d\n", rc);
+ } else {
+ DBG("i2c_client is NULL\n");
+ }
+
+ return rc;
}
-static int write_i2c_seq(U8 addr, U8* buf, U16 size)
+static int write_i2c_seq(unsigned char addr, unsigned char *buf,
+ unsigned short size)
{
- int rc = 0;
- struct i2c_msg msgs[] =
- {
- {
- .addr = addr,
- .flags = 0, // if read flag is undefined, then it means write flag.
- .len = size,
- .buf = buf,
- },
- };
-
- /* If everything went ok (i.e. 1 msg transmitted), return #bytes
- transmitted, else error code. */
- if (i2c_client != NULL)
- {
- rc = i2c_transfer(i2c_client->adapter, msgs, 1);
- if ( rc < 0 )
- {
- DBG("write_i2c_seq() error %d\n", rc);
- }
- }
- else
- {
- DBG("i2c_client is NULL\n");
- }
-
- return rc;
+ int rc = 0;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = addr,
+ /* if read flag is undefined,
+ * then it means write flag.
+ */
+ .flags = 0,
+ .len = size,
+ .buf = buf,
+ },
+ };
+
+ /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+ * transmitted, else error code.
+ */
+ if (i2c_client != NULL) {
+ rc = i2c_transfer(i2c_client->adapter, msgs, 1);
+ if (rc < 0)
+ DBG("write_i2c_seq() error %d\n", rc);
+ } else {
+ DBG("i2c_client is NULL\n");
+ }
+
+ return rc;
}
-static U16 read_reg(U8 bank, U8 addr)
+static unsigned short read_reg(unsigned char bank, unsigned char addr)
{
- U8 tx_data[3] = {0x10, bank, addr};
- U8 rx_data[2] = {0};
+ unsigned char tx_data[3] = {0x10, bank, addr};
+ unsigned char rx_data[2] = {0};
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DBBUS, &rx_data[0], 2);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 3);
+ read_i2c_seq(SLAVE_I2C_ID_DBBUS, &rx_data[0], 2);
- return (rx_data[1] << 8 | rx_data[0]);
+ return rx_data[1] << 8 | rx_data[0];
}
-static void write_reg(U8 bank, U8 addr, U16 data)
+static void write_reg(unsigned char bank, unsigned char addr,
+ unsigned short data)
{
- U8 tx_data[5] = {0x10, bank, addr, data & 0xFF, data >> 8};
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 5);
-}
+ unsigned char tx_data[5] = {0x10, bank, addr, data & 0xFF, data >> 8};
-static void write_reg_8bit(U8 bank, U8 addr, U8 data)
-{
- U8 tx_data[4] = {0x10, bank, addr, data};
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 4);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 5);
}
-void dbbusDWIICEnterSerialDebugMode(void)
+static void write_reg_8bit(unsigned char bank, unsigned char addr,
+ unsigned char data)
{
- U8 data[5];
-
- // Enter the Serial Debug Mode
- data[0] = 0x53;
- data[1] = 0x45;
- data[2] = 0x52;
- data[3] = 0x44;
- data[4] = 0x42;
+ unsigned char tx_data[4] = {0x10, bank, addr, data};
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 5);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 4);
}
-void dbbusDWIICStopMCU(void)
+static void dbbusDWIICEnterSerialDebugMode(void)
{
- U8 data[1];
+ unsigned char data[5];
- // Stop the MCU
- data[0] = 0x37;
+ /* Enter the Serial Debug Mode */
+ data[0] = 0x53;
+ data[1] = 0x45;
+ data[2] = 0x52;
+ data[3] = 0x44;
+ data[4] = 0x42;
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 5);
}
-void dbbusDWIICIICUseBus(void)
+static void dbbusDWIICStopMCU(void)
{
- U8 data[1];
+ unsigned char data[1];
- // IIC Use Bus
- data[0] = 0x35;
+ /* Stop the MCU */
+ data[0] = 0x37;
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
}
-void dbbusDWIICIICReshape(void)
+static void dbbusDWIICIICUseBus(void)
{
- U8 data[1];
+ unsigned char data[1];
- // IIC Re-shape
- data[0] = 0x71;
+ /* IIC Use Bus */
+ data[0] = 0x35;
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
}
-void dbbusDWIICIICNotUseBus(void)
+static void dbbusDWIICIICReshape(void)
{
- U8 data[1];
+ unsigned char data[1];
- // IIC Not Use Bus
- data[0] = 0x34;
+ /* IIC Re-shape */
+ data[0] = 0x71;
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
}
-void dbbusDWIICNotStopMCU(void)
+static unsigned char get_ic_type(void)
{
- U8 data[1];
-
- // Not Stop the MCU
- data[0] = 0x36;
+ unsigned char ic_type = 0;
+ unsigned char bank;
+ unsigned char addr;
+
+ reset_hw();
+ dbbusDWIICEnterSerialDebugMode();
+ dbbusDWIICStopMCU();
+ dbbusDWIICIICUseBus();
+ dbbusDWIICIICReshape();
+ msleep(300);
+
+ /* stop mcu */
+ write_reg_8bit(0x0F, 0xE6, 0x01);
+ /* disable watch dog */
+ write_reg(0x3C, 0x60, 0xAA55);
+ /* get ic type */
+ bank = MSTAR_CHIPTOP_REGISTER_BANK;
+ addr = MSTAR_CHIPTOP_REGISTER_ICTYPE;
+ ic_type = (0xff)&(read_reg(bank, addr));
+
+ if (ic_type != 1 /* msg2133 */
+ && ic_type != 2 /* msg21xxA */
+ && ic_type != 3) /* msg26xxM */ {
+ ic_type = 0;
+ }
+
+ reset_hw();
+
+ return ic_type;
+}
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+static int msg21xx_read_firmware_id(void)
+{
+ unsigned char dbbus_tx_data[3] = {0};
+ unsigned char dbbus_rx_data[4] = {0};
+ int ret = 0;
+
+ dbbus_tx_data[0] = 0x53;
+ dbbus_tx_data[1] = 0x00;
+ dbbus_tx_data[2] = 0x2A;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 3);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4);
+ mutex_unlock(&msg21xx_mutex);
+ pdata->fw_version_major = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0];
+ pdata->fw_version_minor = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2];
+
+ dev_dbg(&i2c_client->dev, "major num = %d, minor num = %d\n",
+ pdata->fw_version_major, pdata->fw_version_minor);
+
+ if (pdata->fw_version == NULL)
+ pdata->fw_version = kzalloc(sizeof(char), GFP_KERNEL);
+
+ snprintf(pdata->fw_version, sizeof(char) * 7, "%03d%03d",
+ pdata->fw_version_major,
+ pdata->fw_version_minor);
+
+ return ret;
}
-void dbbusDWIICExitSerialDebugMode(void)
+static int firmware_erase_c33(enum EMEM_TYPE_t emem_type)
{
- U8 data[1];
+ /* stop mcu */
+ write_reg(0x0F, 0xE6, 0x0001);
- // Exit the Serial Debug Mode
- data[0] = 0x45;
+ /* disable watch dog */
+ write_reg_8bit(0x3C, 0x60, 0x55);
+ write_reg_8bit(0x3C, 0x61, 0xAA);
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ /* set PROGRAM password */
+ write_reg_8bit(0x16, 0x1A, 0xBA);
+ write_reg_8bit(0x16, 0x1B, 0xAB);
- // Delay some interval to guard the next transaction
- //udelay ( 200 ); // delay about 0.2ms
-}
+ write_reg_8bit(0x16, 0x18, 0x80);
-//---------------------------------------------------------------------//
+ if (emem_type == EMEM_ALL)
+ write_reg_8bit(0x16, 0x08, 0x10);
-static U8 get_ic_type(void)
-{
- U8 ic_type = 0;
-
- reset_hw();
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- mdelay ( 300 );
-
- // stop mcu
- write_reg_8bit ( 0x0F, 0xE6, 0x01 );
- // disable watch dog
- write_reg ( 0x3C, 0x60, 0xAA55 );
- // get ic type
- ic_type = (0xff)&(read_reg(0x1E, 0xCC));
-
- if (ic_type != 1 //msg2133
- && ic_type != 2 //msg21xxA
- && ic_type != 3) //msg26xxM
- {
- ic_type = 0;
- }
-
- reset_hw();
-
- return ic_type;
-}
+ write_reg_8bit(0x16, 0x18, 0x40);
+ msleep(20);
-static int get_customer_firmware_version(void)
-{
- U8 dbbus_tx_data[3] = {0};
- U8 dbbus_rx_data[4] = {0};
- int ret = 0;
+ /* clear pce */
+ write_reg_8bit(0x16, 0x18, 0x80);
- DBG("get_customer_firmware_version()\n");
+ /* erase trigger */
+ if (emem_type == EMEM_MAIN)
+ write_reg_8bit(0x16, 0x0E, 0x04); /* erase main */
+ else
+ write_reg_8bit(0x16, 0x0E, 0x08); /* erase all block */
- dbbus_tx_data[0] = 0x53;
- dbbus_tx_data[1] = 0x00;
- dbbus_tx_data[2] = 0x2A;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4);
- mutex_unlock(&msg21xx_mutex);
- fw_version_major = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0];
- fw_version_minor = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2];
+ return 1;
+}
- DBG("*** major = %d ***\n", fw_version_major);
- DBG("*** minor = %d ***\n", fw_version_minor);
+static void _ReadBinConfig(void);
+static unsigned int _CalMainCRC32(void);
- if (fw_version == NULL)
- {
- fw_version = kzalloc(sizeof(char), GFP_KERNEL);
- }
+static int check_fw_update(void)
+{
+ int ret = 0;
+
+ msg21xx_read_firmware_id();
+ _ReadBinConfig();
+ if (main_sw_id == info_sw_id) {
+ if (_CalMainCRC32() == bin_conf_crc32) {
+ /*check upgrading*/
+ if ((update_bin_major == pdata->fw_version_major) &&
+ (update_bin_minor > pdata->fw_version_minor)) {
+ ret = 1;
+ }
+ }
+ }
+ return ret;
- sprintf(fw_version, "%03d%03d", fw_version_major, fw_version_minor);
+}
- return ret;
+static ssize_t firmware_update_c33(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size,
+ enum EMEM_TYPE_t emem_type,
+ bool isForce) {
+ unsigned int i, j;
+ unsigned int crc_main, crc_main_tp;
+ unsigned int crc_info, crc_info_tp;
+ unsigned short reg_data = 0;
+ int update_pass = 1;
+
+ crc_main = 0xffffffff;
+ crc_info = 0xffffffff;
+
+ reset_hw();
+
+ if (!check_fw_update() && !isForce) {
+ DBG("****no need to update\n");
+ reset_hw();
+ FwDataCnt = 0;
+ return size;
+ }
+ reset_hw();
+ msleep(300);
+
+ dbbusDWIICEnterSerialDebugMode();
+ dbbusDWIICStopMCU();
+ dbbusDWIICIICUseBus();
+ dbbusDWIICIICReshape();
+ msleep(300);
+
+ /* erase main */
+ firmware_erase_c33(EMEM_MAIN);
+ msleep(1000);
+
+ reset_hw();
+ dbbusDWIICEnterSerialDebugMode();
+ dbbusDWIICStopMCU();
+ dbbusDWIICIICUseBus();
+ dbbusDWIICIICReshape();
+ msleep(300);
+
+ /* polling 0x3CE4 is 0x1C70 */
+ if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0x1C70);
+ }
+
+ switch (emem_type) {
+ case EMEM_ALL:
+ write_reg(0x3C, 0xE4, 0xE38F); /* for all-blocks */
+ break;
+ case EMEM_MAIN:
+ write_reg(0x3C, 0xE4, 0x7731); /* for main block */
+ break;
+ case EMEM_INFO:
+ write_reg(0x3C, 0xE4, 0x7731); /* for info block */
+
+ write_reg_8bit(0x0F, 0xE6, 0x01);
+
+ write_reg_8bit(0x3C, 0xE4, 0xC5);
+ write_reg_8bit(0x3C, 0xE5, 0x78);
+
+ write_reg_8bit(MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x9F);
+ write_reg_8bit(MSTAR_CHIPTOP_REGISTER_BANK, 0x05, 0x82);
+
+ write_reg_8bit(0x0F, 0xE6, 0x00);
+ msleep(100);
+ break;
+ }
+
+ /* polling 0x3CE4 is 0x2F43 */
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0x2F43);
+
+ /* calculate CRC 32 */
+ _CRC_initTable();
+
+ /* total 32 KB : 2 byte per R/W */
+ for (i = 0; i < 32; i++) {
+ if (i == 31) {
+ fw_bin_data[i][1014] = 0x5A;
+ fw_bin_data[i][1015] = 0xA5;
+
+ for (j = 0; j < 1016; j++)
+ crc_main = _CRC_getValue(fw_bin_data[i][j],
+ crc_main);
+ } else {
+ for (j = 0; j < 1024; j++)
+ crc_main = _CRC_getValue(fw_bin_data[i][j],
+ crc_main);
+ }
+
+ for (j = 0; j < 8; j++)
+ write_i2c_seq(ts_data->client->addr,
+ &fw_bin_data[i][j * 128], 128);
+ msleep(100);
+
+ /* polling 0x3CE4 is 0xD0BC */
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0xD0BC);
+
+ write_reg(0x3C, 0xE4, 0x2F43);
+ }
+
+ if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
+ /* write file done and check crc */
+ write_reg(0x3C, 0xE4, 0x1380);
+ }
+ msleep(20);
+
+ if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
+ /* polling 0x3CE4 is 0x9432 */
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0x9432);
+ }
+
+ crc_main = crc_main ^ 0xffffffff;
+ crc_info = crc_info ^ 0xffffffff;
+
+ if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
+ /* CRC Main from TP */
+ crc_main_tp = read_reg(0x3C, 0x80);
+ crc_main_tp = (crc_main_tp << 16) | read_reg(0x3C, 0x82);
+
+ /* CRC Info from TP */
+ crc_info_tp = read_reg(0x3C, 0xA0);
+ crc_info_tp = (crc_info_tp << 16) | read_reg(0x3C, 0xA2);
+ }
+
+ update_pass = 1;
+ if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
+ if (crc_main_tp != crc_main)
+ update_pass = 0;
+ }
+
+ if (!update_pass) {
+ DBG("update_C33 failed\n");
+ reset_hw();
+ FwDataCnt = 0;
+ return 0;
+ }
+
+ DBG("update_C33 OK\n");
+ reset_hw();
+ FwDataCnt = 0;
+ return size;
}
-static int firmware_erase_c33 ( EMEM_TYPE_t emem_type )
+static unsigned int _CalMainCRC32(void)
{
- // stop mcu
- write_reg ( 0x0F, 0xE6, 0x0001 );
+ unsigned int ret = 0;
+ unsigned short reg_data = 0;
+
+ reset_hw();
- //disable watch dog
- write_reg_8bit ( 0x3C, 0x60, 0x55 );
- write_reg_8bit ( 0x3C, 0x61, 0xAA );
+ dbbusDWIICEnterSerialDebugMode();
+ dbbusDWIICStopMCU();
+ dbbusDWIICIICUseBus();
+ dbbusDWIICIICReshape();
+ msleep(100);
- // set PROGRAM password
- write_reg_8bit ( 0x16, 0x1A, 0xBA );
- write_reg_8bit ( 0x16, 0x1B, 0xAB );
+ /* Stop MCU */
+ write_reg(0x0F, 0xE6, 0x0001);
- write_reg_8bit ( 0x16, 0x18, 0x80 );
+ /* Stop Watchdog */
+ write_reg_8bit(0x3C, 0x60, 0x55);
+ write_reg_8bit(0x3C, 0x61, 0xAA);
- if ( emem_type == EMEM_ALL )
- {
- write_reg_8bit ( 0x16, 0x08, 0x10 ); //mark
- }
+ /* cmd */
+ write_reg(0x3C, 0xE4, 0xDF4C);
+ write_reg(0x1E, 0x04, 0x7d60);
+ /* TP SW reset */
+ write_reg(0x1E, 0x04, 0x829F);
- write_reg_8bit ( 0x16, 0x18, 0x40 );
- mdelay ( 10 );
+ /* MCU run */
+ write_reg(0x0F, 0xE6, 0x0000);
- // clear pce
- write_reg_8bit ( 0x16, 0x18, 0x80 );
+ /* polling 0x3CE4 */
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0x9432);
- // erase trigger
- if ( emem_type == EMEM_MAIN )
- {
- write_reg_8bit ( 0x16, 0x0E, 0x04 ); //erase main
- }
- else
- {
- write_reg_8bit ( 0x16, 0x0E, 0x08 ); //erase all block
- }
+ /* Cal CRC Main from TP */
+ ret = read_reg(0x3C, 0x80);
+ ret = (ret << 16) | read_reg(0x3C, 0x82);
- return ( 1 );
+ DBG("[21xxA]:Current main crc32=0x%x\n", ret);
+ return ret;
}
-static ssize_t firmware_update_c33 ( struct device *dev, struct device_attribute *attr,
- const char *buf, size_t size, EMEM_TYPE_t emem_type )
+static void _ReadBinConfig(void)
{
- U32 i, j;
- U32 crc_main, crc_main_tp;
- U32 crc_info, crc_info_tp;
- U16 reg_data = 0;
- int update_pass = 1;
-
- crc_main = 0xffffffff;
- crc_info = 0xffffffff;
-
- reset_hw();
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- mdelay ( 300 );
-
- //erase main
- firmware_erase_c33 ( EMEM_MAIN );
- mdelay ( 1000 );
-
- reset_hw();
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- mdelay ( 300 );
-
- /////////////////////////
- // Program
- /////////////////////////
-
- //polling 0x3CE4 is 0x1C70
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }
- while ( reg_data != 0x1C70 );
- }
-
- switch ( emem_type )
- {
- case EMEM_ALL:
- write_reg ( 0x3C, 0xE4, 0xE38F ); // for all-blocks
- break;
- case EMEM_MAIN:
- write_reg ( 0x3C, 0xE4, 0x7731 ); // for main block
- break;
- case EMEM_INFO:
- write_reg ( 0x3C, 0xE4, 0x7731 ); // for info block
-
- write_reg_8bit ( 0x0F, 0xE6, 0x01 );
-
- write_reg_8bit ( 0x3C, 0xE4, 0xC5 );
- write_reg_8bit ( 0x3C, 0xE5, 0x78 );
-
- write_reg_8bit ( 0x1E, 0x04, 0x9F );
- write_reg_8bit ( 0x1E, 0x05, 0x82 );
-
- write_reg_8bit ( 0x0F, 0xE6, 0x00 );
- mdelay ( 100 );
- break;
- }
-
- // polling 0x3CE4 is 0x2F43
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }
- while ( reg_data != 0x2F43 );
-
- // calculate CRC 32
- _CRC_initTable ();
-
- for ( i = 0; i < 32; i++ ) // total 32 KB : 2 byte per R/W
- {
- if ( i == 31 )
- {
- temp[i][1014] = 0x5A;
- temp[i][1015] = 0xA5;
-
- for ( j = 0; j < 1016; j++ )
- {
- crc_main = _CRC_getValue ( temp[i][j], crc_main);
- }
- }
- else
- {
- for ( j = 0; j < 1024; j++ )
- {
- crc_main = _CRC_getValue ( temp[i][j], crc_main);
- }
- }
-
- //write_i2c_seq(SLAVE_I2C_ID_DWI2C, temp[i], 1024);
- for (j = 0; j < 8; j++)
- {
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &temp[i][j*128], 128 );
- }
- msleep (100);
-
- // polling 0x3CE4 is 0xD0BC
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }
- while ( reg_data != 0xD0BC );
-
- write_reg ( 0x3C, 0xE4, 0x2F43 );
- }
-
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- // write file done and check crc
- write_reg ( 0x3C, 0xE4, 0x1380 );
- }
- mdelay ( 10 );
-
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- // polling 0x3CE4 is 0x9432
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }while ( reg_data != 0x9432 );
- }
-
- crc_main = crc_main ^ 0xffffffff;
- crc_info = crc_info ^ 0xffffffff;
-
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- // CRC Main from TP
- crc_main_tp = read_reg ( 0x3C, 0x80 );
- crc_main_tp = ( crc_main_tp << 16 ) | read_reg ( 0x3C, 0x82 );
-
- // CRC Info from TP
- crc_info_tp = read_reg ( 0x3C, 0xA0 );
- crc_info_tp = ( crc_info_tp << 16 ) | read_reg ( 0x3C, 0xA2 );
- }
-
- update_pass = 1;
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- if ( crc_main_tp != crc_main )
- update_pass = 0;
-
- /*
- if ( crc_info_tp != crc_info )
- update_pass = 0;
- */
- }
-
- if ( !update_pass )
- {
- DBG( "update_C33 failed\n" );
- reset_hw();
- FwDataCnt = 0;
- return 0;
- }
-
- DBG( "update_C33 OK\n" );
- reset_hw();
- FwDataCnt = 0;
- return size;
+ unsigned char dbbus_tx_data[5] = {0};
+ unsigned char dbbus_rx_data[4] = {0};
+ unsigned short reg_data = 0;
+
+ reset_hw();
+
+ dbbusDWIICEnterSerialDebugMode();
+ dbbusDWIICStopMCU();
+ dbbusDWIICIICUseBus();
+ dbbusDWIICIICReshape();
+ msleep(100);
+
+ /* Stop MCU */
+ write_reg(0x0F, 0xE6, 0x0001);
+
+ /* Stop Watchdog */
+ write_reg_8bit(0x3C, 0x60, 0x55);
+ write_reg_8bit(0x3C, 0x61, 0xAA);
+
+ /* cmd */
+ write_reg(0x3C, 0xE4, 0xA4AB);
+ write_reg(MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x7d60);
+ /* TP SW reset */
+ write_reg(0x1E, 0x04, 0x829F);
+ /* TP SW reset*/
+
+ /* MCU run */
+ write_reg(0x0F, 0xE6, 0x0000);
+
+ /* polling 0x3CE4 */
+ do {
+ reg_data = read_reg(0x3C, 0xE4);
+ } while (reg_data != 0x5B58);
+
+ dbbus_tx_data[0] = 0x72;
+ dbbus_tx_data[1] = 0x7F;
+ dbbus_tx_data[2] = 0x55;
+ dbbus_tx_data[3] = 0x00;
+ dbbus_tx_data[4] = 0x04;
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 5);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4);
+ if ((dbbus_rx_data[0] >= 0x30 && dbbus_rx_data[0] <= 0x39)
+ && (dbbus_rx_data[1] >= 0x30 && dbbus_rx_data[1] <= 0x39)
+ && (dbbus_rx_data[2] >= 0x31 && dbbus_rx_data[2] <= 0x39)) {
+ main_sw_id = (dbbus_rx_data[0] - 0x30) * 100 +
+ (dbbus_rx_data[1] - 0x30) * 10 +
+ (dbbus_rx_data[2] - 0x30);
+ }
+
+ dbbus_tx_data[0] = 0x72;
+ dbbus_tx_data[1] = 0x7F;
+ dbbus_tx_data[2] = 0xFC;
+ dbbus_tx_data[3] = 0x00;
+ dbbus_tx_data[4] = 0x04;
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 5);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4);
+ bin_conf_crc32 = dbbus_rx_data[0];
+ bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[1];
+ bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[2];
+ bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[3];
+
+ dbbus_tx_data[0] = 0x72;
+ dbbus_tx_data[1] = 0x83;
+ dbbus_tx_data[2] = 0x00;
+ dbbus_tx_data[3] = 0x00;
+ dbbus_tx_data[4] = 0x04;
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 5);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4);
+ if ((dbbus_rx_data[0] >= 0x30 && dbbus_rx_data[0] <= 0x39)
+ && (dbbus_rx_data[1] >= 0x30 && dbbus_rx_data[1] <= 0x39)
+ && (dbbus_rx_data[2] >= 0x31 && dbbus_rx_data[2] <= 0x39)) {
+ info_sw_id = (dbbus_rx_data[0] - 0x30) * 100 +
+ (dbbus_rx_data[1] - 0x30) * 10 +
+ (dbbus_rx_data[2] - 0x30);
+ }
+
+ DBG("[21xxA]:main_sw_id = %d, info_sw_id = %d, bin_conf_crc32=0x%x\n",
+ main_sw_id, info_sw_id, bin_conf_crc32);
}
-#ifdef FIRMWARE_AUTOUPDATE
-unsigned short main_sw_id = 0x7FF, info_sw_id = 0x7FF;
-U32 bin_conf_crc32 = 0;
-
-static U32 _CalMainCRC32(void)
+static ssize_t firmware_update_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
- U32 ret=0;
- U16 reg_data=0;
-
- reset_hw();
-
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- msleep ( 100 );
+ DBG("*** firmware_update_show() pdata->fw_version = %s ***\n",
+ pdata->fw_version);
- //Stop MCU
- write_reg ( 0x0F, 0xE6, 0x0001 );
-
- // Stop Watchdog
- write_reg_8bit ( 0x3C, 0x60, 0x55 );
- write_reg_8bit ( 0x3C, 0x61, 0xAA );
-
- //cmd
- write_reg ( 0x3C, 0xE4, 0xDF4C );
- write_reg ( 0x1E, 0x04, 0x7d60 );
- // TP SW reset
- write_reg ( 0x1E, 0x04, 0x829F );
+ return snprintf(buf, sizeof(char) - 1, "%s\n", pdata->fw_version);
+}
- //MCU run
- write_reg ( 0x0F, 0xE6, 0x0000 );
+static ssize_t firmware_update_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ bFwUpdating = 1;
+ disable_irq(ts_data->client->irq);
- //polling 0x3CE4
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }while ( reg_data != 0x9432 );
+ DBG("*** update fw size = %d ***\n", FwDataCnt);
+ size = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, false);
- // Cal CRC Main from TP
- ret = read_reg ( 0x3C, 0x80 );
- ret = ( ret << 16 ) | read_reg ( 0x3C, 0x82 );
+ enable_irq(ts_data->client->irq);
+ bFwUpdating = 0;
- DBG("[21xxA]:Current main crc32=0x%x\n",ret);
- return (ret);
+ return size;
}
-static void _ReadBinConfig ( void )
-{
- U8 dbbus_tx_data[5]={0};
- U8 dbbus_rx_data[4]={0};
- U16 reg_data=0;
-
- reset_hw();
-
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- msleep ( 100 );
-
- //Stop MCU
- write_reg ( 0x0F, 0xE6, 0x0001 );
-
- // Stop Watchdog
- write_reg_8bit ( 0x3C, 0x60, 0x55 );
- write_reg_8bit ( 0x3C, 0x61, 0xAA );
-
- //cmd
- write_reg ( 0x3C, 0xE4, 0xA4AB );
- write_reg ( 0x1E, 0x04, 0x7d60 );
-
- // TP SW reset
- write_reg ( 0x1E, 0x04, 0x829F );
-
- //MCU run
- write_reg ( 0x0F, 0xE6, 0x0000 );
-
- //polling 0x3CE4
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }
- while ( reg_data != 0x5B58 );
-
- dbbus_tx_data[0] = 0x72;
- dbbus_tx_data[1] = 0x7F;
- dbbus_tx_data[2] = 0x55;
- dbbus_tx_data[3] = 0x00;
- dbbus_tx_data[4] = 0x04;
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 5 );
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4 );
- if ((dbbus_rx_data[0]>=0x30 && dbbus_rx_data[0]<=0x39)
- &&(dbbus_rx_data[1]>=0x30 && dbbus_rx_data[1]<=0x39)
- &&(dbbus_rx_data[2]>=0x31 && dbbus_rx_data[2]<=0x39))
- {
- main_sw_id = (dbbus_rx_data[0]-0x30)*100+(dbbus_rx_data[1]-0x30)*10+(dbbus_rx_data[2]-0x30);
- }
-
- dbbus_tx_data[0] = 0x72;
- dbbus_tx_data[1] = 0x7F;
- dbbus_tx_data[2] = 0xFC;
- dbbus_tx_data[3] = 0x00;
- dbbus_tx_data[4] = 0x04;
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 5 );
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4 );
- bin_conf_crc32 = dbbus_rx_data[0];
- bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[1];
- bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[2];
- bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[3];
-
- dbbus_tx_data[0] = 0x72;
- dbbus_tx_data[1] = 0x83;
- dbbus_tx_data[2] = 0x00;
- dbbus_tx_data[3] = 0x00;
- dbbus_tx_data[4] = 0x04;
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 5 );
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4 );
- if ((dbbus_rx_data[0]>=0x30 && dbbus_rx_data[0]<=0x39)
- &&(dbbus_rx_data[1]>=0x30 && dbbus_rx_data[1]<=0x39)
- &&(dbbus_rx_data[2]>=0x31 && dbbus_rx_data[2]<=0x39))
- {
- info_sw_id = (dbbus_rx_data[0]-0x30)*100+(dbbus_rx_data[1]-0x30)*10+(dbbus_rx_data[2]-0x30);
- }
-
- DBG("[21xxA]:main_sw_id = %d, info_sw_id = %d, bin_conf_crc32=0x%x\n", main_sw_id, info_sw_id, bin_conf_crc32);
-}
+static DEVICE_ATTR(update, (S_IRUGO | S_IWUSR),
+ firmware_update_show,
+ firmware_update_store);
-static int fwAutoUpdate(void *unused)
+static int prepare_fw_data(struct device *dev)
{
- int time = 0;
- ssize_t ret = 0;
-
- for (time = 0; time < 5; time++)
- {
- DBG("fwAutoUpdate time = %d\n",time);
- ret = firmware_update_c33(NULL, NULL, NULL, 1, EMEM_MAIN);
- if (ret == 1)
- {
- DBG("AUTO_UPDATE OK!!!");
- break;
- }
- }
- if (time == 5)
- {
- DBG("AUTO_UPDATE failed!!!");
- }
- enable_irq(irq_msg21xx);
- return 0;
+ int count;
+ int i;
+ int ret;
+ const struct firmware *fw = NULL;
+
+ ret = request_firmware(&fw, pdata->fw_name, dev);
+ if (ret < 0) {
+ dev_err(dev, "Request firmware failed - %s (%d)\n",
+ pdata->fw_name, ret);
+ return ret;
+ }
+ DBG("*** prepare_fw_data() ret = %d, size = %d***\n", ret, fw->size);
+
+ count = fw->size / 1024;
+
+ for (i = 0; i < count; i++) {
+ memcpy(fw_bin_data[FwDataCnt], fw->data + (i * 1024), 1024);
+ FwDataCnt++;
+ }
+ update_bin_major = (fw->data[0x7f4f] << 8) + fw->data[0x7f4e];
+ update_bin_minor = (fw->data[0x7f51] << 8) + fw->data[0x7f50];
+ DBG("*** prepare_fw_data bin major = %d ***\n", update_bin_major);
+ DBG("*** prepare_fw_data bin minor = %d ***\n", update_bin_minor);
+
+ DBG("***FwDataCnt = %d ***\n", FwDataCnt);
+
+ return fw->size;
}
-#endif
-//------------------------------------------------------------------------------//
-static ssize_t firmware_update_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t firmware_update_smart_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
{
- DBG("*** firmware_update_show() fw_version = %s ***\n", fw_version);
+ int ret;
- return sprintf(buf, "%s\n", fw_version);
+ ret = prepare_fw_data(dev);
+ if (ret < 0) {
+ dev_err(dev, "Request firmware failed -(%d)\n", ret);
+ return ret;
+ }
+ bFwUpdating = 1;
+ disable_irq(ts_data->client->irq);
+
+ DBG("*** update fw size = %d ***\n", FwDataCnt);
+ ret = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, false);
+ if (ret == 0)
+ DBG("*** firmware_update_c33 ret = %d ***\n", ret);
+
+ enable_irq(ts_data->client->irq);
+ bFwUpdating = 0;
+
+ return ret;
}
-static ssize_t firmware_update_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
+static ssize_t firmware_force_update_smart_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
{
- bFwUpdating = 1;
- disable_irq(irq_msg21xx);
+ int ret;
- DBG("*** update fw size = %d ***\n", FwDataCnt);
- size = firmware_update_c33 (dev, attr, buf, size, EMEM_MAIN);
+ ret = prepare_fw_data(dev);
+ if (ret < 0) {
+ dev_err(dev, "Request firmware failed -(%d)\n", ret);
+ return ret;
+ }
+ bFwUpdating = 1;
+ disable_irq(ts_data->client->irq);
- enable_irq(irq_msg21xx);
- bFwUpdating = 0;
+ DBG("*** update fw size = %d ***\n", FwDataCnt);
+ ret = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, true);
+ if (ret == 0)
+ DBG("*** firmware_update_c33 et = %d ***\n", ret);
- return size;
+ enable_irq(ts_data->client->irq);
+ bFwUpdating = 0;
+
+ return ret;
}
-static DEVICE_ATTR(update, SYSFS_AUTHORITY, firmware_update_show, firmware_update_store);
+static DEVICE_ATTR(update_fw, (S_IRUGO | S_IWUSR),
+ firmware_update_show,
+ firmware_update_smart_store);
+
+static DEVICE_ATTR(force_update_fw, (S_IRUGO | S_IWUSR),
+ firmware_update_show,
+ firmware_force_update_smart_store);
static ssize_t firmware_version_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
- DBG("*** firmware_version_show() fw_version = %s ***\n", fw_version);
-
- return sprintf(buf, "%s\n", fw_version);
+ msg21xx_read_firmware_id();
+ return snprintf(buf, 8, "%s\n", pdata->fw_version);
}
static ssize_t firmware_version_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
{
- get_customer_firmware_version();
+ msg21xx_read_firmware_id();
+ DBG("*** firmware_version_store() pdata->fw_version = %s ***\n",
+ pdata->fw_version);
+
+ return size;
+}
- DBG("*** firmware_version_store() fw_version = %s ***\n", fw_version);
+static DEVICE_ATTR(version, (S_IRUGO | S_IWUSR),
+ firmware_version_show,
+ firmware_version_store);
- return size;
+
+static ssize_t msg21xx_fw_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, MSTAR_FW_NAME_MAX_LEN - 1, "%s\n", pdata->fw_name);
}
-static DEVICE_ATTR(version, SYSFS_AUTHORITY, firmware_version_show, firmware_version_store);
+static ssize_t msg21xx_fw_name_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+
+ if (size > MSTAR_FW_NAME_MAX_LEN - 1)
+ return -EINVAL;
+
+ strlcpy(pdata->fw_name, buf, size);
+ if (pdata->fw_name[size - 1] == '\n')
+ pdata->fw_name[size - 1] = 0;
+
+ return size;
+}
+
+static DEVICE_ATTR(fw_name, (S_IRUGO | S_IWUSR),
+ msg21xx_fw_name_show, msg21xx_fw_name_store);
static ssize_t firmware_data_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
- DBG("*** firmware_data_show() FwDataCnt = %d ***\n", FwDataCnt);
+ DBG("*** firmware_data_show() FwDataCnt = %d ***\n", FwDataCnt);
- return FwDataCnt;
+ return FwDataCnt;
}
static ssize_t firmware_data_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
{
- int count = size / 1024;
- int i;
+ int count = size / 1024;
+ int i;
- for (i = 0; i < count; i ++)
- {
- memcpy(temp[FwDataCnt], buf+(i*1024), 1024);
+ for (i = 0; i < count; i++) {
+ memcpy(fw_bin_data[FwDataCnt], buf + (i * 1024), 1024);
- FwDataCnt ++;
- }
+ FwDataCnt++;
+ }
- DBG("***FwDataCnt = %d ***\n", FwDataCnt);
+ DBG("***FwDataCnt = %d ***\n", FwDataCnt);
- if (buf != NULL)
- {
- DBG("*** buf[0] = %c ***\n", buf[0]);
- }
+ if (buf != NULL)
+ DBG("*** buf[0] = %c ***\n", buf[0]);
- return size;
+ return size;
}
-static DEVICE_ATTR(data, SYSFS_AUTHORITY, firmware_data_show, firmware_data_store);
+static DEVICE_ATTR(data, (S_IRUGO | S_IWUSR),
+ firmware_data_show, firmware_data_store);
#ifdef TP_PRINT
static ssize_t tp_print_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
- tp_print_proc_read();
+ tp_print_proc_read();
- return sprintf(buf, "%d\n", bTpInSuspend);
+ return snprintf(buf, sizeof(char) - 1, "%d\n", ts_data->suspended);
}
static ssize_t tp_print_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
{
- DBG("*** tp_print_store() ***\n");
+ DBG("*** tp_print_store() ***\n");
- return size;
+ return size;
}
-static DEVICE_ATTR(tpp, SYSFS_AUTHORITY, tp_print_show, tp_print_store);
+static DEVICE_ATTR(tpp, (S_IRUGO | S_IWUSR),
+ tp_print_show, tp_print_store);
#endif
-//------------------------------------------------------------------------------//
#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
static void _msg_enable_proximity(void)
{
- U8 tx_data[4] = {0};
-
- DBG("_msg_enable_proximity!");
- tx_data[0] = 0x52;
- tx_data[1] = 0x00;
- tx_data[2] = 0x47;
- tx_data[3] = 0xa0;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &tx_data[0], 4);
- mutex_unlock(&msg21xx_mutex);
-
- bEnableTpProximity = 1;
+ unsigned char tx_data[4] = {0};
+
+ DBG("_msg_enable_proximity!");
+ tx_data[0] = 0x52;
+ tx_data[1] = 0x00;
+ tx_data[2] = 0x47;
+ tx_data[3] = 0xa0;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr, &tx_data[0], 4);
+ mutex_unlock(&msg21xx_mutex);
+
+ bEnableTpProximity = 1;
}
static void _msg_disable_proximity(void)
{
- U8 tx_data[4] = {0};
-
- DBG("_msg_disable_proximity!");
- tx_data[0] = 0x52;
- tx_data[1] = 0x00;
- tx_data[2] = 0x47;
- tx_data[3] = 0xa1;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &tx_data[0], 4);
- mutex_unlock(&msg21xx_mutex);
-
- bEnableTpProximity = 0;
- bFaceClosingTp = 0;
+ unsigned char tx_data[4] = {0};
+
+ DBG("_msg_disable_proximity!");
+ tx_data[0] = 0x52;
+ tx_data[1] = 0x00;
+ tx_data[2] = 0x47;
+ tx_data[3] = 0xa1;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr, &tx_data[0], 4);
+ mutex_unlock(&msg21xx_mutex);
+
+ bEnableTpProximity = 0;
+ bFaceClosingTp = 0;
}
-void tsps_msg21xx_enable(int en)
+static void tsps_msg21xx_enable(int en)
{
- if (en)
- {
- _msg_enable_proximity();
- }
- else
- {
- _msg_disable_proximity();
- }
+ if (en)
+ _msg_enable_proximity();
+ else
+ _msg_disable_proximity();
}
-int tsps_msg21xx_data(void)
+static int tsps_msg21xx_data(void)
{
- return bFaceClosingTp;
+ return bFaceClosingTp;
}
#endif
-static U8 calculate_checksum(U8 *msg, S32 length)
+static int msg21xx_pinctrl_init(void)
{
- S32 Checksum = 0;
- S32 i;
+ int retval;
+
+ /* Get pinctrl if target uses pinctrl */
+ ts_data->ts_pinctrl = devm_pinctrl_get(&(i2c_client->dev));
+ if (IS_ERR_OR_NULL(ts_data->ts_pinctrl)) {
+ retval = PTR_ERR(ts_data->ts_pinctrl);
+ dev_dbg(&i2c_client->dev,
+ "Target does not use pinctrl %d\n", retval);
+ goto err_pinctrl_get;
+ }
+
+ ts_data->pinctrl_state_active = pinctrl_lookup_state(
+ ts_data->ts_pinctrl, PINCTRL_STATE_ACTIVE);
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_active)) {
+ retval = PTR_ERR(ts_data->pinctrl_state_active);
+ dev_dbg(&i2c_client->dev,
+ "Can't lookup %s pinstate %d\n",
+ PINCTRL_STATE_ACTIVE, retval);
+ goto err_pinctrl_lookup;
+ }
+
+ ts_data->pinctrl_state_suspend = pinctrl_lookup_state(
+ ts_data->ts_pinctrl, PINCTRL_STATE_SUSPEND);
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_suspend)) {
+ retval = PTR_ERR(ts_data->pinctrl_state_suspend);
+ dev_dbg(&i2c_client->dev,
+ "Can't lookup %s pinstate %d\n",
+ PINCTRL_STATE_SUSPEND, retval);
+ goto err_pinctrl_lookup;
+ }
+
+ ts_data->pinctrl_state_release = pinctrl_lookup_state(
+ ts_data->ts_pinctrl, PINCTRL_STATE_RELEASE);
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ retval = PTR_ERR(ts_data->pinctrl_state_release);
+ dev_dbg(&i2c_client->dev,
+ "Can't lookup %s pinstate %d\n",
+ PINCTRL_STATE_RELEASE, retval);
+ }
+
+ return 0;
+
+err_pinctrl_lookup:
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+err_pinctrl_get:
+ ts_data->ts_pinctrl = NULL;
+ return retval;
+}
- for (i = 0; i < length; i ++)
- {
- Checksum += msg[i];
- }
+static unsigned char calculate_checksum(unsigned char *msg, int length)
+{
+ int checksum = 0, i;
- return (U8)((-Checksum) & 0xFF);
+ for (i = 0; i < length; i++)
+ checksum += msg[i];
+
+ return (unsigned char)((-checksum) & 0xFF);
}
-static S32 parse_info(touchInfo_t *info)
+static int parse_info(struct touchInfo_t *info)
{
- U8 data[DEMO_MODE_PACKET_LENGTH] = {0};
- U8 checksum = 0;
- U32 x = 0, y = 0;
- U32 x2 = 0, y2 = 0;
- U32 delta_x = 0, delta_y = 0;
-
- mutex_lock(&msg21xx_mutex);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &data[0], DEMO_MODE_PACKET_LENGTH);
- mutex_unlock(&msg21xx_mutex);
- checksum = calculate_checksum(&data[0], (DEMO_MODE_PACKET_LENGTH-1));
- DBG("check sum: [%x] == [%x]? \n", data[DEMO_MODE_PACKET_LENGTH-1], checksum);
-
- if(data[DEMO_MODE_PACKET_LENGTH-1] != checksum)
- {
- DBG("WRONG CHECKSUM\n");
- return -1;
- }
-
- if(data[0] != 0x52)
- {
- DBG("WRONG HEADER\n");
- return -1;
- }
-
- info->keycode = 0xFF;
- if ((data[1] == 0xFF) && (data[2] == 0xFF) && (data[3] == 0xFF) && (data[4] == 0xFF) && (data[6] == 0xFF))
- {
- if ((data[5] == 0xFF) || (data[5] == 0))
- {
- info->keycode = 0xFF;
- }
- else if ((data[5] == 1) || (data[5] == 2) || (data[5] == 4) || (data[5] == 8))
- {
- if (data[5] == 1)
- {
- info->keycode = 0;
- }
- else if (data[5] == 2)
- {
- info->keycode = 1;
- }
- else if (data[5] == 4)
- {
- info->keycode = 2;
- }
- else if (data[5] == 8)
- {
- info->keycode = 3;
- }
- }
- #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- else if (bEnableTpProximity &&((data[5] == 0x80) || (data[5] == 0x40)))
- {
- if (data[5] == 0x80)
- {
- bFaceClosingTp = 1;
- }
- else if (data[5] == 0x40)
- {
- bFaceClosingTp = 0;
- }
- DBG("bEnableTpProximity=%d; bFaceClosingTp=%d; data[5]=%x;\n", bEnableTpProximity, bFaceClosingTp, data[5]);
- return -1;
- }
- #endif
- else
- {
- DBG("WRONG KEY\n");
- return -1;
- }
- }
- else
- {
- x = (((data[1] & 0xF0 ) << 4) | data[2]);
- y = ((( data[1] & 0x0F) << 8) | data[3]);
- delta_x = (((data[4] & 0xF0) << 4 ) | data[5]);
- delta_y = (((data[4] & 0x0F) << 8 ) | data[6]);
-
- if ((delta_x == 0) && (delta_y == 0))
- {
- info->point[0].x = x * TOUCH_SCREEN_X_MAX / TPD_WIDTH;
- info->point[0].y = y * TOUCH_SCREEN_Y_MAX/ TPD_HEIGHT;
- info->count = 1;
- }
- else
- {
- if (delta_x > 2048)
- {
- delta_x -= 4096;
- }
- if (delta_y > 2048)
- {
- delta_y -= 4096;
- }
- x2 = (U32)((S16)x + (S16)delta_x);
- y2 = (U32)((S16)y + (S16)delta_y);
- info->point[0].x = x * TOUCH_SCREEN_X_MAX / TPD_WIDTH;
- info->point[0].y = y * TOUCH_SCREEN_Y_MAX/ TPD_HEIGHT;
- info->point[1].x = x2 * TOUCH_SCREEN_X_MAX / TPD_WIDTH;
- info->point[1].y = y2 * TOUCH_SCREEN_Y_MAX/ TPD_HEIGHT;
- info->count = 2;
- }
- }
-
- return 0;
+ unsigned char data[DEMO_MODE_PACKET_LENGTH] = {0};
+ unsigned char checksum = 0;
+ unsigned int x = 0, y = 0;
+ unsigned int x2 = 0, y2 = 0;
+ unsigned int delta_x = 0, delta_y = 0;
+
+ mutex_lock(&msg21xx_mutex);
+ read_i2c_seq(ts_data->client->addr, &data[0], DEMO_MODE_PACKET_LENGTH);
+ mutex_unlock(&msg21xx_mutex);
+ checksum = calculate_checksum(&data[0], (DEMO_MODE_PACKET_LENGTH-1));
+ DBG("check sum: [%x] == [%x]?\n",
+ data[DEMO_MODE_PACKET_LENGTH-1], checksum);
+
+ if (data[DEMO_MODE_PACKET_LENGTH-1] != checksum) {
+ DBG("WRONG CHECKSUM\n");
+ return -EINVAL;
+ }
+
+ if (data[0] != 0x52) {
+ DBG("WRONG HEADER\n");
+ return -EINVAL;
+ }
+
+ info->keycode = 0xFF;
+ if ((data[1] == 0xFF) && (data[2] == 0xFF) &&
+ (data[3] == 0xFF) && (data[4] == 0xFF) &&
+ (data[6] == 0xFF)) {
+ if ((data[5] == 0xFF) || (data[5] == 0)) {
+ info->keycode = 0xFF;
+ } else if ((data[5] == 1) || (data[5] == 2) ||
+ (data[5] == 4) || (data[5] == 8)) {
+ info->keycode = data[5] >> 1;
+
+ DBG("info->keycode index %d\n", info->keycode);
+ }
+ #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
+ else if (bEnableTpProximity && ((data[5] == 0x80) ||
+ (data[5] == 0x40))) {
+ if (data[5] == 0x80)
+ bFaceClosingTp = 1;
+ else if (data[5] == 0x40)
+ bFaceClosingTp = 0;
+
+ return -EINVAL;
+ }
+ #endif
+ else {
+ DBG("WRONG KEY\n");
+ return -EINVAL;
+ }
+ } else {
+ x = (((data[1] & 0xF0) << 4) | data[2]);
+ y = (((data[1] & 0x0F) << 8) | data[3]);
+ delta_x = (((data[4] & 0xF0) << 4) | data[5]);
+ delta_y = (((data[4] & 0x0F) << 8) | data[6]);
+
+ if ((delta_x == 0) && (delta_y == 0)) {
+ info->point[0].x = x * pdata->x_max / TPD_WIDTH;
+ info->point[0].y = y * pdata->y_max / TPD_HEIGHT;
+ info->count = 1;
+ } else {
+ if (delta_x > 2048)
+ delta_x -= 4096;
+
+ if (delta_y > 2048)
+ delta_y -= 4096;
+
+ x2 = (unsigned int)((signed short)x +
+ (signed short)delta_x);
+ y2 = (unsigned int)((signed short)y +
+ (signed short)delta_y);
+ info->point[0].x = x * pdata->x_max / TPD_WIDTH;
+ info->point[0].y = y * pdata->y_max / TPD_HEIGHT;
+ info->point[1].x = x2 * pdata->x_max / TPD_WIDTH;
+ info->point[1].y = y2 * pdata->y_max / TPD_HEIGHT;
+ info->count = 2;
+ }
+ }
+
+ return 0;
}
-static void touch_driver_touch_pressed(int x, int y)
+static void touch_driver_touch_released(void)
{
- DBG("point touch pressed");
+ int i;
+
+ DBG("point touch released\n");
+
+ for (i = 0; i < MAX_TOUCH_NUM; i++) {
+ input_mt_slot(input_dev, i);
+ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 0);
+ }
- input_report_key(input_dev, BTN_TOUCH, 1);
- input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 1);
- input_report_abs(input_dev, ABS_MT_POSITION_X, x);
- input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
- input_mt_sync(input_dev);
+ input_report_key(input_dev, BTN_TOUCH, 0);
+ input_report_key(input_dev, BTN_TOOL_FINGER, 0);
+ input_sync(input_dev);
}
-static void touch_driver_touch_released(void)
+/* read data through I2C then report data to input
+ *sub-system when interrupt occurred
+ */
+static irqreturn_t msg21xx_ts_interrupt(int irq, void *dev_id)
{
- DBG("point touch released");
+ struct touchInfo_t info;
+ int i = 0;
+ static int last_keycode = 0xFF;
+ static int last_count;
+
+ DBG("touch_driver_do_work()\n");
+
+ memset(&info, 0x0, sizeof(info));
+ if (parse_info(&info) == 0) {
+ #ifdef CONFIG_TP_HAVE_KEY
+ if (info.keycode != 0xFF) { /* key touch pressed */
+ if (info.keycode < num_buttons) {
+ if (info.keycode != last_keycode) {
+ DBG("key touch pressed");
+
+ input_report_key(input_dev,
+ BTN_TOUCH, 1);
+ input_report_key(input_dev,
+ button_map[info.keycode], 1);
+
+ last_keycode = info.keycode;
+ } else {
+ /* pass duplicate key-pressing */
+ DBG("REPEATED KEY\n");
+ }
+ } else {
+ DBG("WRONG KEY\n");
+ }
+ } else { /* key touch released */
+ if (last_keycode != 0xFF) {
+ DBG("key touch released");
+
+ input_report_key(input_dev,
+ BTN_TOUCH, 0);
+ input_report_key(input_dev,
+ button_map[last_keycode],
+ 0);
+
+ last_keycode = 0xFF;
+ }
+ }
+ #endif /* CONFIG_TP_HAVE_KEY */
+
+ if (info.count > 0) { /* point touch pressed */
+ for (i = 0; i < info.count; i++) {
+ input_mt_slot(input_dev, i);
+ input_mt_report_slot_state(input_dev,
+ MT_TOOL_FINGER, 1);
+ input_report_abs(input_dev,
+ ABS_MT_TOUCH_MAJOR, 1);
+ input_report_abs(input_dev,
+ ABS_MT_POSITION_X,
+ info.point[i].x);
+ input_report_abs(input_dev,
+ ABS_MT_POSITION_Y,
+ info.point[i].y);
+ }
+ }
+
+ if (last_count > info.count) {
+ for (i = info.count; i < MAX_TOUCH_NUM; i++) {
+ input_mt_slot(input_dev, i);
+ input_mt_report_slot_state(input_dev,
+ MT_TOOL_FINGER, 0);
+ }
+ }
+ last_count = info.count;
+
+ input_report_key(input_dev, BTN_TOUCH, info.count > 0);
+ input_report_key(input_dev, BTN_TOOL_FINGER, info.count > 0);
+
+ input_sync(input_dev);
+ }
+
+ return IRQ_HANDLED;
+}
- input_report_key(input_dev, BTN_TOUCH, 0);
- input_mt_sync(input_dev);
+
+static int msg21xx_ts_power_init(void)
+{
+ int rc;
+
+ ts_data->vdd = regulator_get(&i2c_client->dev, "vdd");
+ if (IS_ERR(ts_data->vdd)) {
+ rc = PTR_ERR(ts_data->vdd);
+ dev_err(&i2c_client->dev,
+ "Regulator get failed vdd rc=%d\n", rc);
+ return rc;
+ }
+
+ if (regulator_count_voltages(ts_data->vdd) > 0) {
+ rc = regulator_set_voltage(ts_data->vdd, MSTAR_VTG_MIN_UV,
+ MSTAR_VTG_MAX_UV);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator set_vtg failed vdd rc=%d\n", rc);
+ goto reg_vdd_put;
+ }
+ }
+
+ ts_data->vcc_i2c = regulator_get(&i2c_client->dev, "vcc_i2c");
+ if (IS_ERR(ts_data->vcc_i2c)) {
+ rc = PTR_ERR(ts_data->vcc_i2c);
+ dev_err(&i2c_client->dev,
+ "Regulator get failed vcc_i2c rc=%d\n", rc);
+ goto reg_vdd_set_vtg;
+ }
+
+ if (regulator_count_voltages(ts_data->vcc_i2c) > 0) {
+ rc = regulator_set_voltage(ts_data->vcc_i2c,
+ MSTAR_I2C_VTG_MIN_UV,
+ MSTAR_I2C_VTG_MAX_UV);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
+ goto reg_vcc_i2c_put;
+ }
+ }
+
+ return 0;
+
+reg_vcc_i2c_put:
+ regulator_put(ts_data->vcc_i2c);
+reg_vdd_set_vtg:
+ if (regulator_count_voltages(ts_data->vdd) > 0)
+ regulator_set_voltage(ts_data->vdd, 0, MSTAR_VTG_MAX_UV);
+reg_vdd_put:
+ regulator_put(ts_data->vdd);
+ return rc;
}
-/* read data through I2C then report data to input sub-system when interrupt occurred */
-void touch_driver_do_work(struct work_struct *work)
+
+static int msg21xx_ts_power_deinit(void)
{
- touchInfo_t info;
- int i = 0;
- static int last_keycode = 0xFF;
- static int last_count = 0;
-
- DBG("touch_driver_do_work()\n");
-
- memset(&info, 0x0, sizeof(info));
- if (0 == parse_info(&info))
- {
- #ifdef CONFIG_TP_HAVE_KEY
- if (info.keycode != 0xFF) //key touch pressed
- {
- DBG("touch_driver_do_work() info.keycode=%x, last_keycode=%x, tp_key_array[%d]=%d\n", info.keycode, last_keycode, info.keycode, tp_key_array[info.keycode]);
- if (info.keycode < MAX_KEY_NUM)
- {
- if (info.keycode != last_keycode)
- {
- DBG("key touch pressed");
-
- input_report_key(input_dev, BTN_TOUCH, 1);
- input_report_key(input_dev, tp_key_array[info.keycode], 1);
-
- last_keycode = info.keycode;
- }
- else
- {
- /// pass duplicate key-pressing
- DBG("REPEATED KEY\n");
- }
- }
- else
- {
- DBG("WRONG KEY\n");
- }
- }
- else //key touch released
- {
- if (last_keycode != 0xFF)
- {
- DBG("key touch released");
-
- input_report_key(input_dev, BTN_TOUCH, 0);
- input_report_key(input_dev, tp_key_array[last_keycode], 0);
-
- last_keycode = 0xFF;
- }
- }
- #endif //CONFIG_TP_HAVE_KEY
-
- if (info.count > 0) //point touch pressed
- {
- for (i = 0; i < info.count; i ++)
- {
- touch_driver_touch_pressed(info.point[i].x, info.point[i].y);
- }
- last_count = info.count;
- }
- else if (last_count > 0) //point touch released
- {
- touch_driver_touch_released();
- last_count = 0;
- }
-
- input_sync(input_dev);
- }
-
- enable_irq(irq_msg21xx);
+ if (regulator_count_voltages(ts_data->vdd) > 0)
+ regulator_set_voltage(ts_data->vdd, 0, MSTAR_VTG_MAX_UV);
+
+ regulator_put(ts_data->vdd);
+
+ if (regulator_count_voltages(ts_data->vcc_i2c) > 0)
+ regulator_set_voltage(ts_data->vcc_i2c, 0,
+ MSTAR_I2C_VTG_MAX_UV);
+
+ regulator_put(ts_data->vcc_i2c);
+ return 0;
}
-/* The interrupt service routine will be triggered when interrupt occurred */
-irqreturn_t touch_driver_isr(int irq, void *dev_id)
+static int msg21xx_ts_power_on(void)
{
- DBG("touch_driver_isr()\n");
+ int rc;
+
+ rc = regulator_enable(ts_data->vdd);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator vdd enable failed rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = regulator_enable(ts_data->vcc_i2c);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator vcc_i2c enable failed rc=%d\n", rc);
+ regulator_disable(ts_data->vdd);
+ }
+
+ return rc;
+}
- disable_irq_nosync(irq_msg21xx);
- schedule_work(&msg21xx_wk);
+static int msg21xx_ts_power_off(void)
+{
+ int rc;
+
+ DBG("*** %s ***\n", __func__);
+ rc = regulator_disable(vdd);
+ rc = regulator_disable(ts_data->vdd);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator vdd disable failed rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = regulator_disable(ts_data->vcc_i2c);
+ if (rc) {
+ dev_err(&i2c_client->dev,
+ "Regulator vcc_i2c disable failed rc=%d\n", rc);
+ rc = regulator_enable(ts_data->vdd);
+ }
+
+ return rc;
+}
- return IRQ_HANDLED;
+static int msg21xx_ts_gpio_configure(bool on)
+{
+ int ret = 0;
+
+ if (on) {
+ if (gpio_is_valid(pdata->irq_gpio)) {
+ ret = gpio_request(pdata->irq_gpio, "msg21xx_irq_gpio");
+ if (ret) {
+ dev_err(&i2c_client->dev,
+ "Failed to request GPIO[%d], %d\n",
+ pdata->irq_gpio, ret);
+ goto err_irq_gpio_req;
+ }
+ ret = gpio_direction_input(pdata->irq_gpio);
+ if (ret) {
+ dev_err(&i2c_client->dev,
+ "Failed to set direction for gpio[%d], %d\n",
+ pdata->irq_gpio, ret);
+ goto err_irq_gpio_dir;
+ }
+ gpio_set_value_cansleep(pdata->irq_gpio, 1);
+ } else {
+ dev_err(&i2c_client->dev, "irq gpio not provided\n");
+ goto err_irq_gpio_req;
+ }
+
+ if (gpio_is_valid(pdata->reset_gpio)) {
+ ret = gpio_request(pdata->reset_gpio,
+ "msg21xx_reset_gpio");
+ if (ret) {
+ dev_err(&i2c_client->dev,
+ "Failed to request GPIO[%d], %d\n",
+ pdata->reset_gpio, ret);
+ goto err_reset_gpio_req;
+ }
+
+ /* power on TP */
+ ret = gpio_direction_output(pdata->reset_gpio, 1);
+ if (ret) {
+ dev_err(&i2c_client->dev,
+ "Failed to set direction for GPIO[%d], %d\n",
+ pdata->reset_gpio, ret);
+ goto err_reset_gpio_dir;
+ }
+ msleep(100);
+ gpio_set_value_cansleep(pdata->reset_gpio, 0);
+ msleep(20);
+ gpio_set_value_cansleep(pdata->reset_gpio, 1);
+ msleep(200);
+ } else {
+ dev_err(&i2c_client->dev, "reset gpio not provided\n");
+ goto err_reset_gpio_req;
+ }
+
+ } else {
+ if (gpio_is_valid(pdata->irq_gpio))
+ gpio_free(pdata->irq_gpio);
+ if (gpio_is_valid(pdata->reset_gpio)) {
+ gpio_set_value_cansleep(pdata->reset_gpio, 0);
+ ret = gpio_direction_input(pdata->reset_gpio);
+ if (ret)
+ dev_err(&i2c_client->dev,
+ "Unable to set direction for gpio [%d]\n",
+ pdata->reset_gpio);
+ gpio_free(pdata->reset_gpio);
+ }
+ }
+ return 0;
+err_reset_gpio_dir:
+ if (gpio_is_valid(pdata->reset_gpio))
+ gpio_free(pdata->irq_gpio);
+err_reset_gpio_req:
+err_irq_gpio_dir:
+ if (gpio_is_valid(pdata->irq_gpio))
+ gpio_free(pdata->irq_gpio);
+err_irq_gpio_req:
+ return ret;
}
-#if defined(CONFIG_FB)
-static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data)
+#ifdef CONFIG_PM
+static int msg21xx_ts_resume(struct device *dev)
{
- struct fb_event *evdata = data;
- int *blank;
-
- if (evdata && evdata->data && event == FB_EVENT_BLANK )
- {
- blank = evdata->data;
- if (*blank == FB_BLANK_UNBLANK)
- {
- if (bTpInSuspend)
- {
- gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(200);
-
- touch_driver_touch_released();
- input_sync(input_dev);
-
- enable_irq(irq_msg21xx);
- }
- bTpInSuspend = 0;
- }
- else if (*blank == FB_BLANK_POWERDOWN)
- {
- if (bFwUpdating)
- {
- DBG("suspend bFwUpdating=%d\n", bFwUpdating);
- return 0;
- }
-
- #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- if (bEnableTpProximity)
- {
- DBG("suspend bEnableTpProximity=%d\n", bEnableTpProximity);
- return 0;
- }
- #endif
-
- if (bTpInSuspend == 0)
- {
- disable_irq(irq_msg21xx);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- }
- bTpInSuspend = 1;
- }
- }
-
- return 0;
+ int retval;
+
+ mutex_lock(&ts_data->ts_mutex);
+ if (ts_data->suspended) {
+ if (ts_data->ts_pinctrl) {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_active);
+ if (retval < 0) {
+ dev_err(dev, "Cannot get active pinctrl state\n");
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+ }
+
+ retval = msg21xx_ts_gpio_configure(true);
+ if (retval) {
+ dev_err(dev, "Failed to put gpios in active state %d",
+ retval);
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+
+ enable_irq(ts_data->client->irq);
+
+ retval = msg21xx_ts_power_on();
+ if (retval) {
+ dev_err(dev, "msg21xx_ts power on failed");
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+
+ ts_data->suspended = 0;
+ } else {
+ dev_info(dev, "msg21xx_ts already in resume\n");
+ }
+ mutex_unlock(&ts_data->ts_mutex);
+
+ return 0;
}
-#endif
-#ifdef CONFIG_HAS_EARLYSUSPEND
-void touch_driver_early_suspend(struct early_suspend *p)
+static int msg21xx_ts_suspend(struct device *dev)
{
- DBG("touch_driver_early_suspend()\n");
+ int retval;
- if (bFwUpdating)
- {
- DBG("suspend bFwUpdating=%d\n", bFwUpdating);
- return;
- }
+ if (bFwUpdating) {
+ DBG("suspend bFwUpdating=%d\n", bFwUpdating);
+ return 0;
+ }
#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- if (bEnableTpProximity)
- {
- DBG("suspend bEnableTpProximity=%d\n", bEnableTpProximity);
- return;
- }
+ if (bEnableTpProximity) {
+ DBG("suspend bEnableTpProximity=%d\n", bEnableTpProximity);
+ return 0;
+ }
#endif
- if (bTpInSuspend == 0)
- {
- disable_irq(irq_msg21xx);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- }
- bTpInSuspend = 1;
+ mutex_lock(&ts_data->ts_mutex);
+ if (ts_data->suspended == 0) {
+ disable_irq(ts_data->client->irq);
+
+ touch_driver_touch_released();
+
+ retval = msg21xx_ts_power_off();
+ if (retval) {
+ dev_err(dev, "msg21xx_ts power off failed");
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+
+ if (ts_data->ts_pinctrl) {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_suspend);
+ if (retval < 0) {
+ dev_err(&i2c_client->dev, "Cannot get idle pinctrl state\n");
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+ }
+
+ retval = msg21xx_ts_gpio_configure(false);
+ if (retval) {
+ dev_err(dev, "Failed to put gpios in idle state %d",
+ retval);
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+
+ ts_data->suspended = 1;
+ } else {
+ dev_err(dev, "msg21xx_ts already in suspend\n");
+ }
+ mutex_unlock(&ts_data->ts_mutex);
+
+
+ return 0;
}
-
-void touch_driver_early_resume(struct early_suspend *p)
+#else
+static int msg21xx_ts_resume(struct device *dev)
+{
+ return 0;
+}
+static int msg21xx_ts_suspend(struct device *dev)
{
- DBG("touch_driver_early_resume() bTpInSuspend=%d\n", bTpInSuspend);
-
- if (bTpInSuspend)
- {
- gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(200);
-
- touch_driver_touch_released();
- input_sync(input_dev);
-
- enable_irq(irq_msg21xx);
- }
- bTpInSuspend = 0;
+ return 0;
}
#endif
-/* probe function is used for matching and initializing input device */
-static int touch_driver_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+#if defined(CONFIG_FB)
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
{
-#ifdef FIRMWARE_AUTOUPDATE
- unsigned short update_bin_major = 0, update_bin_minor = 0;
- int i, update_flag = 0;
+ struct fb_event *evdata = data;
+ int *blank;
+
+ if (evdata && evdata->data && event == FB_EVENT_BLANK) {
+ blank = evdata->data;
+ if (*blank == FB_BLANK_UNBLANK)
+ msg21xx_ts_resume(&i2c_client->dev);
+ else if (*blank == FB_BLANK_POWERDOWN)
+ msg21xx_ts_suspend(&i2c_client->dev);
+ }
+
+ return 0;
+}
#endif
- int ret = 0;
-
- if (input_dev != NULL)
- {
- DBG("input device has found\n");
- return -1;
- }
-
- DBG("*** %s ***\n", __FUNCTION__);
-
- i2c_client = client;
-
- ret = gpio_request(MS_TS_MSG21XX_GPIO_RST, "reset");
- if (ret < 0)
- {
- pr_err("*** Failed to request GPIO %d, error %d ***\n", MS_TS_MSG21XX_GPIO_RST, ret);
- goto err0;
- }
-
- // power on TP
- gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(100);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(200);
- if (0 == get_ic_type())
- {
- pr_err("the currnet ic is not Mstar\n");
- ret = -1;
- goto err0;
- }
-
- mutex_init(&msg21xx_mutex);
-
- /* allocate an input device */
- input_dev = input_allocate_device();
- if (!input_dev)
- {
- ret = -ENOMEM;
- pr_err("*** input device allocation failed ***\n");
- goto err1;
- }
-
- input_dev->name = client->name;
- input_dev->phys = "I2C";
- input_dev->dev.parent = &client->dev;
- input_dev->id.bustype = BUS_I2C;
-
- /* set the supported event type for input device */
- set_bit(EV_ABS, input_dev->evbit);
- set_bit(EV_SYN, input_dev->evbit);
- set_bit(EV_KEY, input_dev->evbit);
- set_bit(BTN_TOUCH, input_dev->keybit);
- set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+static int msg21xx_get_dt_coords(struct device *dev, char *name,
+ struct msg21xx_ts_platform_data *pdata)
+{
+ u32 coords[FT_COORDS_ARR_SIZE];
+ struct property *prop;
+ struct device_node *np = dev->of_node;
+ int coords_size, rc;
+
+ prop = of_find_property(np, name, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ coords_size = prop->length / sizeof(u32);
+ if (coords_size != FT_COORDS_ARR_SIZE) {
+ dev_err(dev, "invalid %s\n", name);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(np, name, coords, coords_size);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read %s\n", name);
+ return rc;
+ }
+
+ if (!strcmp(name, "mstar,panel-coords")) {
+ pdata->panel_minx = coords[0];
+ pdata->panel_miny = coords[1];
+ pdata->panel_maxx = coords[2];
+ pdata->panel_maxy = coords[3];
+ } else if (!strcmp(name, "mstar,display-coords")) {
+ pdata->x_min = coords[0];
+ pdata->y_min = coords[1];
+ pdata->x_max = coords[2];
+ pdata->y_max = coords[3];
+ } else {
+ dev_err(dev, "unsupported property %s\n", name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int msg21xx_parse_dt(struct device *dev,
+ struct msg21xx_ts_platform_data *pdata)
+{
+ int rc;
+ struct device_node *np = dev->of_node;
+ struct property *prop;
+ u32 temp_val;
+
+ rc = msg21xx_get_dt_coords(dev, "mstar,panel-coords", pdata);
+ if (rc && (rc != -EINVAL))
+ return rc;
+
+ rc = msg21xx_get_dt_coords(dev, "mstar,display-coords", pdata);
+ if (rc)
+ return rc;
+
+ /* reset, irq gpio info */
+ pdata->reset_gpio = of_get_named_gpio_flags(np, "mstar,reset-gpio",
+ 0, &pdata->reset_gpio_flags);
+ if (pdata->reset_gpio < 0)
+ return pdata->reset_gpio;
+
+ pdata->irq_gpio = of_get_named_gpio_flags(np, "mstar,irq-gpio",
+ 0, &pdata->irq_gpio_flags);
+ if (pdata->irq_gpio < 0)
+ return pdata->irq_gpio;
+
+
+ prop = of_find_property(np, "mstar,button-map", NULL);
+ if (prop) {
+ num_buttons = prop->length / sizeof(temp_val);
+ if (num_buttons > MAX_BUTTONS)
+ return -EINVAL;
+
+ rc = of_property_read_u32_array(np,
+ "mstar,button-map", button_map,
+ num_buttons);
+ if (rc) {
+ dev_err(dev, "Unable to read key codes\n");
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/* probe function is used for matching and initializing input device */
+static int msg21xx_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id) {
+
+ int ret = 0;
+
+ if (input_dev != NULL) {
+ DBG("input device has found\n");
+ return -EINVAL;
+ }
+
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct msg21xx_ts_platform_data), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ ret = msg21xx_parse_dt(&client->dev, pdata);
+ if (ret) {
+ dev_err(&client->dev, "DT parsing failed\n");
+ return ret;
+ }
+ } else
+ pdata = client->dev.platform_data;
+
+ ts_data = devm_kzalloc(&client->dev,
+ sizeof(struct msg21xx_ts_data), GFP_KERNEL);
+ if (!ts_data)
+ return -ENOMEM;
+
+ DBG("*** %s ***\n", __func__);
+
+ i2c_client = client;
+
+ ret = msg21xx_ts_power_init();
+ if (ret)
+ dev_err(&client->dev, "Mstar power init failed\n");
+
+ ret = msg21xx_ts_power_on();
+ if (ret) {
+ dev_err(&client->dev, "Mstar power on failed\n");
+ goto exit_deinit_power;
+ }
+
+ ret = msg21xx_pinctrl_init();
+ if (!ret && ts_data->ts_pinctrl) {
+ ret = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_active);
+ if (ret < 0)
+ goto exit_pinctrl_select;
+ } else {
+ goto exit_pinctrl_init;
+ }
+
+ ret = msg21xx_ts_gpio_configure(true);
+ if (ret) {
+ dev_err(&client->dev, "Failed to configure gpio %d\n", ret);
+ goto exit_gpio_config;
+ }
+
+ if (get_ic_type() == 0) {
+ pr_err("the currnet ic is not Mstar\n");
+ ret = -1;
+ goto err_wrong_ic_type;
+ }
+
+ mutex_init(&msg21xx_mutex);
+ mutex_init(&ts_data->ts_mutex);
+
+ /* allocate an input device */
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ ret = -ENOMEM;
+ pr_err("*** input device allocation failed ***\n");
+ goto err_input_allocate_dev;
+ }
+
+ input_dev->name = client->name;
+ input_dev->phys = "I2C";
+ input_dev->dev.parent = &client->dev;
+ input_dev->id.bustype = BUS_I2C;
+
+ /* set the supported event type for input device */
+ set_bit(EV_ABS, input_dev->evbit);
+ set_bit(EV_SYN, input_dev->evbit);
+ set_bit(EV_KEY, input_dev->evbit);
+ set_bit(BTN_TOUCH, input_dev->keybit);
+ set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+ set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+ ts_data->input_dev = input_dev;
+ ts_data->client = client;
+ ts_data->pdata = pdata;
+
+ input_set_drvdata(input_dev, ts_data);
+ i2c_set_clientdata(client, ts_data);
#ifdef CONFIG_TP_HAVE_KEY
- {
- int i;
- for (i = 0; i < MAX_KEY_NUM; i ++)
- {
- input_set_capability(input_dev, EV_KEY, tp_key_array[i]);
- }
- }
+ {
+ int i;
+
+ for (i = 0; i < num_buttons; i++)
+ input_set_capability(input_dev, EV_KEY, button_map[i]);
+ }
#endif
- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 2, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_X, TOUCH_SCREEN_X_MIN, TOUCH_SCREEN_X_MAX, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_Y, TOUCH_SCREEN_Y_MIN, TOUCH_SCREEN_Y_MAX, 0, 0);
-
- /* register the input device to input sub-system */
- ret = input_register_device(input_dev);
- if (ret < 0)
- {
- pr_err("*** Unable to register ms-touchscreen input device ***\n");
- goto err1;
- }
-
- /* set sysfs for firmware */
- firmware_class = class_create(THIS_MODULE, "ms-touchscreen-msg20xx"); //client->name
- if (IS_ERR(firmware_class))
- pr_err("Failed to create class(firmware)!\n");
-
- firmware_cmd_dev = device_create(firmware_class, NULL, 0, NULL, "device");
- if (IS_ERR(firmware_cmd_dev))
- pr_err("Failed to create device(firmware_cmd_dev)!\n");
-
- // version
- if (device_create_file(firmware_cmd_dev, &dev_attr_version) < 0)
- pr_err("Failed to create device file(%s)!\n", dev_attr_version.attr.name);
- // update
- if (device_create_file(firmware_cmd_dev, &dev_attr_update) < 0)
- pr_err("Failed to create device file(%s)!\n", dev_attr_update.attr.name);
- // data
- if (device_create_file(firmware_cmd_dev, &dev_attr_data) < 0)
- pr_err("Failed to create device file(%s)!\n", dev_attr_data.attr.name);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+ 0, 2, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+ 0, pdata->x_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+ 0, pdata->y_max, 0, 0);
+ ret = input_mt_init_slots(input_dev, MAX_TOUCH_NUM, 0);
+ if (ret) {
+ pr_err("Error %d initialising slots\n", ret);
+ goto err_free_mem;
+ }
+
+ /* register the input device to input sub-system */
+ ret = input_register_device(input_dev);
+ if (ret < 0) {
+ pr_err("*** Unable to register ms-touchscreen input device ***\n");
+ goto err_input_reg_dev;
+ }
+
+ /* set sysfs for firmware */
+ firmware_class = class_create(THIS_MODULE, "ms-touchscreen-msg21xx");
+ if (IS_ERR(firmware_class))
+ pr_err("Failed to create class(firmware)!\n");
+
+ firmware_cmd_dev = device_create(firmware_class, NULL, 0,
+ NULL, "device");
+ if (IS_ERR(firmware_cmd_dev))
+ pr_err("Failed to create device(firmware_cmd_dev)!\n");
+
+ /* version */
+ if (device_create_file(firmware_cmd_dev, &dev_attr_version) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_version.attr.name);
+ /* update */
+ if (device_create_file(firmware_cmd_dev, &dev_attr_update) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_update.attr.name);
+ /* data */
+ if (device_create_file(firmware_cmd_dev, &dev_attr_data) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_data.attr.name);
+ /* fw name*/
+ if (device_create_file(firmware_cmd_dev, &dev_attr_fw_name) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_fw_name.attr.name);
+ /* smart fw update*/
+ if (device_create_file(firmware_cmd_dev, &dev_attr_update_fw) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_update_fw.attr.name);
+ /* smart fw force update*/
+ if (device_create_file(firmware_cmd_dev, &dev_attr_force_update_fw) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_force_update_fw.attr.name);
#ifdef TP_PRINT
- tp_print_create_entry();
+ tp_print_create_entry();
#endif
- dev_set_drvdata(firmware_cmd_dev, NULL);
-
- /* initialize the work queue */
- INIT_WORK(&msg21xx_wk, touch_driver_do_work);
-
- ret = gpio_request(MS_TS_MSG21XX_GPIO_INT, "interrupt");
- if (ret < 0)
- {
- pr_err("*** Failed to request GPIO %d, error %d ***\n", MS_TS_MSG21XX_GPIO_INT, ret);
- goto err2;
- }
- gpio_direction_input(MS_TS_MSG21XX_GPIO_INT);
- gpio_set_value(MS_TS_MSG21XX_GPIO_INT, 1);
+ dev_set_drvdata(firmware_cmd_dev, NULL);
- irq_msg21xx = gpio_to_irq(MS_TS_MSG21XX_GPIO_INT);
+ ret = request_threaded_irq(client->irq, NULL,
+ msg21xx_ts_interrupt,
+ pdata->irq_gpio_flags | IRQF_ONESHOT,
+ "msg21xx", ts_data);
+ if (ret)
+ goto err_req_irq;
- /* request an irq and register the isr */
- ret = request_irq(irq_msg21xx, touch_driver_isr, IRQF_TRIGGER_RISING, "msg21xx", NULL);
- if (ret != 0)
- {
- pr_err("*** Unable to claim irq %d; error %d ***\n", MS_TS_MSG21XX_GPIO_INT, ret);
- goto err3;
- }
-
- disable_irq(irq_msg21xx);
+ disable_irq(ts_data->client->irq);
#if defined(CONFIG_FB)
- msg21xx_fb_notif.notifier_call = fb_notifier_callback;
- ret = fb_register_client(&msg21xx_fb_notif);
-#elif defined (CONFIG_HAS_EARLYSUSPEND)
- mstar_ts_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
- mstar_ts_early_suspend.suspend = touch_driver_early_suspend;
- mstar_ts_early_suspend.resume = touch_driver_early_resume;
- register_early_suspend(&mstar_ts_early_suspend);
+ ts_data->fb_notif.notifier_call = fb_notifier_callback;
+ ret = fb_register_client(&ts_data->fb_notif);
#endif
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- tsps_assist_register_callback("msg21xx", &tsps_msg21xx_enable, &tsps_msg21xx_data);
+#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
+ tsps_assist_register_callback("msg21xx", &tsps_msg21xx_enable,
+ &tsps_msg21xx_data);
#endif
#ifdef FIRMWARE_AUTOUPDATE
- get_customer_firmware_version();
- _ReadBinConfig();
-
- if (main_sw_id == info_sw_id)
- {
- if (_CalMainCRC32() == bin_conf_crc32)
- {
- if ((main_sw_id >= SWID_START) && (main_sw_id < SWID_NULL))
- {
- update_bin_major= (MSG_FIRMWARE[main_sw_id-SWID_START][0x7f4f] << 8) + MSG_FIRMWARE[main_sw_id-SWID_START][0x7f4e];
- update_bin_minor= (MSG_FIRMWARE[main_sw_id-SWID_START][0x7f51] << 8) + MSG_FIRMWARE[main_sw_id-SWID_START][0x7f50];
-
- //check upgrading
- if ((update_bin_major == fw_version_major) && (update_bin_minor > fw_version_minor))
- {
- update_flag = 1;
- }
- }
- DBG("MAIN sw_id=%d,update_flag=%d,update_bin_major=%d,update_bin_minor=%d\n",main_sw_id,update_flag,update_bin_major,update_bin_minor);
- }
- else
- {
- if ((info_sw_id >= SWID_START) && (info_sw_id < SWID_NULL))
- {
- update_bin_major= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4f] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4e];
- update_bin_minor= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f51] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f50];
- update_flag = 1;
- }
- DBG("INFO1 sw_id=%d,update_flag=%d,update_bin_major=%d,update_bin_minor=%d\n",info_sw_id,update_flag,update_bin_major,update_bin_minor);
- }
- }
- else
- {
- if ((info_sw_id >= SWID_START) && (info_sw_id < SWID_NULL))
- {
- update_bin_major= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4f] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4e];
- update_bin_minor= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f51] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f50];
- update_flag = 1;
- }
- DBG("INFO2 sw_id=%d,update_flag=%d,update_bin_major=%d,update_bin_minor=%d\n",info_sw_id,update_flag,update_bin_major,update_bin_minor);
- }
-
- if (update_flag == 1)
- {
- DBG("MSG21XX_fw_auto_update begin....\n");
- //transfer data
- for (i = 0; i < 33; i++)
- {
- firmware_data_store(NULL, NULL, &(MSG_FIRMWARE[info_sw_id-SWID_START][i*1024]), 1024);
- }
-
- kthread_run(fwAutoUpdate, 0, "MSG21XX_fw_auto_update");
- DBG("*** mstar touch screen registered ***\n");
- return 0;
- }
-
- reset_hw();
+ get_customer_firmware_version();
+ _ReadBinConfig();
+
+ if (main_sw_id == info_sw_id) {
+ if (_CalMainCRC32() == bin_conf_crc32) {
+ if ((main_sw_id >= SWID_START) &&
+ (main_sw_id < SWID_NULL)) {
+ update_bin_major = (MSG_FIRMWARE
+ [main_sw_id - SWID_START][0x7f4f] << 8)
+ + MSG_FIRMWARE[main_sw_id - SWID_START][0x7f4e];
+ update_bin_minor = (MSG_FIRMWARE
+ [main_sw_id - SWID_START][0x7f51] << 8)
+ + MSG_FIRMWARE[main_sw_id - SWID_START][0x7f50];
+
+ /* check upgrading */
+ if ((update_bin_major == fw_version_major) &&
+ (update_bin_minor > fw_version_minor)) {
+ update_flag = 1;
+ }
+ }
+ } else {
+ if ((info_sw_id >= SWID_START) &&
+ (info_sw_id < SWID_NULL)) {
+ update_bin_major = (MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f4f] << 8)
+ + MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f4e];
+ update_bin_minor = (MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f51] << 8)
+ + MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f50];
+ update_flag = 1;
+ }
+ }
+ } else {
+ if ((info_sw_id >= SWID_START) && (info_sw_id < SWID_NULL)) {
+ update_bin_major = (MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f4f] << 8)
+ + MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f4e];
+ update_bin_minor = (MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f51] << 8)
+ + MSG_FIRMWARE
+ [info_sw_id - SWID_START][0x7f50];
+ update_flag = 1;
+ }
+ }
+
+ if (update_flag == 1) {
+ DBG("MSG21XX_fw_auto_update begin....\n");
+ /* transfer data */
+ for (i = 0; i < 33; i++) {
+ firmware_data_store(NULL, NULL,
+ &(MSG_FIRMWARE[info_sw_id - SWID_START][i * 1024]),
+ 1024);
+ }
+
+ kthread_run(fwAutoUpdate, 0, "MSG21XX_fw_auto_update");
+ DBG("*** mstar touch screen registered ***\n");
+ return 0;
+ }
+
+ reset_hw();
#endif
- DBG("*** mstar touch screen registered ***\n");
- enable_irq(irq_msg21xx);
- return 0;
-
-err3:
- free_irq(irq_msg21xx, input_dev);
-
-err2:
- gpio_free(MS_TS_MSG21XX_GPIO_INT);
-
-err1:
- mutex_destroy(&msg21xx_mutex);
- input_unregister_device(input_dev);
- input_free_device(input_dev);
- input_dev = NULL;
-
-err0:
- gpio_free(MS_TS_MSG21XX_GPIO_RST);
-
- return ret;
+ DBG("*** mstar touch screen registered ***\n");
+ enable_irq(ts_data->client->irq);
+ return 0;
+
+err_req_irq:
+ free_irq(ts_data->client->irq, ts_data);
+
+err_input_reg_dev:
+err_input_allocate_dev:
+ mutex_destroy(&msg21xx_mutex);
+ mutex_destroy(&ts_data->ts_mutex);
+ input_unregister_device(input_dev);
+ input_free_device(input_dev);
+ input_dev = NULL;
+
+err_wrong_ic_type:
+ msg21xx_ts_gpio_configure(false);
+exit_gpio_config:
+exit_pinctrl_select:
+ if (ts_data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+ ts_data->ts_pinctrl = NULL;
+ } else {
+ ret = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_release);
+ if (ret < 0)
+ pr_err("Cannot get release pinctrl state\n");
+ }
+ }
+exit_pinctrl_init:
+ msg21xx_ts_power_off();
+exit_deinit_power:
+ msg21xx_ts_power_deinit();
+err_free_mem:
+ input_free_device(input_dev);
+
+ return ret;
}
-/* remove function is triggered when the input device is removed from input sub-system */
+/* remove function is triggered when the input device is removed
+ *from input sub-system
+ */
static int touch_driver_remove(struct i2c_client *client)
{
- DBG("touch_driver_remove()\n");
-
- free_irq(irq_msg21xx, input_dev);
- gpio_free(MS_TS_MSG21XX_GPIO_INT);
- gpio_free(MS_TS_MSG21XX_GPIO_RST);
- input_unregister_device(input_dev);
- mutex_destroy(&msg21xx_mutex);
-
- return 0;
+ int retval = 0;
+
+ DBG("touch_driver_remove()\n");
+
+ free_irq(ts_data->client->irq, ts_data);
+ gpio_free(pdata->irq_gpio);
+ gpio_free(pdata->reset_gpio);
+
+ if (ts_data->ts_pinctrl) {
+ if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
+ devm_pinctrl_put(ts_data->ts_pinctrl);
+ ts_data->ts_pinctrl = NULL;
+ } else {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_release);
+ if (retval < 0)
+ pr_err("Cannot get release pinctrl state\n");
+ }
+ }
+
+ input_unregister_device(input_dev);
+ mutex_destroy(&msg21xx_mutex);
+ mutex_destroy(&ts_data->ts_mutex);
+
+ return retval;
}
-/* The I2C device list is used for matching I2C device and I2C device driver. */
-static const struct i2c_device_id touch_device_id[] =
-{
- {"msg21xx", 0},
- {}, /* should not omitted */
+/* The I2C device list is used for matching I2C device
+ *and I2C device driver.
+ */
+static const struct i2c_device_id touch_device_id[] = {
+ {"msg21xx", 0},
+ {}, /* should not omitted */
};
-MODULE_DEVICE_TABLE(i2c, touch_device_id);
-
-static struct i2c_driver touch_device_driver =
-{
- .driver = {
- .name = "msg21xx",
- .owner = THIS_MODULE,
- },
- .probe = touch_driver_probe,
- .remove = touch_driver_remove,
- .id_table = touch_device_id,
+static const struct of_device_id msg21xx_match_table[] = {
+ { .compatible = "mstar,msg21xx", },
+ { },
};
-static int __init touch_driver_init(void)
-{
- int ret;
-
- /* register driver */
- ret = i2c_add_driver(&touch_device_driver);
- if (ret < 0)
- {
- DBG("add touch_device_driver i2c driver failed.\n");
- return -ENODEV;
- }
- DBG("add touch_device_driver i2c driver.\n");
-
- return ret;
-}
+MODULE_DEVICE_TABLE(i2c, touch_device_id);
-static void __exit touch_driver_exit(void)
-{
- DBG("remove touch_device_driver i2c driver.\n");
+static struct i2c_driver touch_device_driver = {
+ .driver = {
+ .name = "ms-msg21xx",
+ .owner = THIS_MODULE,
+ .of_match_table = msg21xx_match_table,
+ },
+ .probe = msg21xx_ts_probe,
+ .remove = touch_driver_remove,
+ .id_table = touch_device_id,
+};
- i2c_del_driver(&touch_device_driver);
-}
+module_i2c_driver(touch_device_driver);
#ifdef TP_PRINT
#include <linux/proc_fs.h>
-static U16 InfoAddr = 0x0F, PoolAddr = 0x10, TransLen = 256;
-static U8 row, units, cnt;
+static unsigned short InfoAddr = 0x0F, PoolAddr = 0x10, TransLen = 256;
+static unsigned char row, units, cnt;
static int tp_print_proc_read(void)
{
- U16 i, j;
- U16 left, offset = 0;
- U8 dbbus_tx_data[3] = {0};
- U8 u8Data;
- S16 s16Data;
- S32 s32Data;
- char *buf = NULL;
-
- left = cnt*row*units;
- if ((bTpInSuspend == 0) && (InfoAddr != 0x0F) && (PoolAddr != 0x10) && (left > 0))
- {
- buf = kmalloc(left, GFP_KERNEL);
- if (buf != NULL)
- {
- printk("tpp: \n");
-
- while (left > 0)
- {
- dbbus_tx_data[0] = 0x53;
- dbbus_tx_data[1] = ((PoolAddr + offset) >> 8) & 0xFF;
- dbbus_tx_data[2] = (PoolAddr + offset) & 0xFF;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &buf[offset], left > TransLen ? TransLen : left);
- mutex_unlock(&msg21xx_mutex);
-
- if (left > TransLen)
- {
- left -= TransLen;
- offset += TransLen;
- }
- else
- {
- left = 0;
- }
- }
-
- for (i = 0; i < cnt; i++)
- {
- printk("tpp: ");
- for (j = 0; j < row; j++)
- {
- if (units == 1)
- {
- u8Data = buf[i*row*units + j*units];
- printk("%d\t", u8Data);
- }
- else if (units == 2)
- {
- s16Data = buf[i*row*units + j*units] + (buf[i*row*units + j*units + 1] << 8);
- printk("%d\t", s16Data);
- }
- else if (units == 4)
- {
- s32Data = buf[i*row*units + j*units] + (buf[i*row*units + j*units + 1] << 8) + (buf[i*row*units + j*units + 2] << 16) + (buf[i*row*units + j*units + 3] << 24);
- printk("%d\t", s32Data);
- }
- }
- printk("\n");
- }
-
- kfree(buf);
- }
- }
-
- return 0;
+ unsigned short i, j;
+ unsigned short left, offset = 0;
+ unsigned char dbbus_tx_data[3] = {0};
+ unsigned char u8Data;
+ signed short s16Data;
+ int s32Data;
+ char *buf = NULL;
+
+ left = cnt*row*units;
+ if ((ts_data->suspended == 0) &&
+ (InfoAddr != 0x0F) &&
+ (PoolAddr != 0x10) &&
+ (left > 0)) {
+ buf = kmalloc(left, GFP_KERNEL);
+ if (buf != NULL) {
+
+ while (left > 0) {
+ dbbus_tx_data[0] = 0x53;
+ dbbus_tx_data[1] = ((PoolAddr + offset) >> 8)
+ & 0xFF;
+ dbbus_tx_data[2] = (PoolAddr + offset) & 0xFF;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr,
+ &dbbus_tx_data[0], 3);
+ read_i2c_seq(ts_data->client->addr,
+ &buf[offset],
+ left > TransLen ? TransLen : left);
+ mutex_unlock(&msg21xx_mutex);
+
+ if (left > TransLen) {
+ left -= TransLen;
+ offset += TransLen;
+ } else {
+ left = 0;
+ }
+ }
+
+ for (i = 0; i < cnt; i++) {
+ for (j = 0; j < row; j++) {
+ if (units == 1) {
+ u8Data = buf[i * row * units +
+ j * units];
+ } else if (units == 2) {
+ s16Data = buf[i * row * units +
+ j * units] +
+ (buf[i * row * units +
+ j * units + 1] << 8);
+ } else if (units == 4) {
+ s32Data = buf[i * row * units +
+ j * units] +
+ (buf[i * row * units +
+ j * units + 1] << 8) +
+ (buf[i * row * units +
+ j * units + 2] << 16) +
+ (buf[i * row * units +
+ j * units + 3] << 24);
+ }
+ }
+ }
+
+ kfree(buf);
+ }
+ }
+
+ return 0;
}
static void tp_print_create_entry(void)
{
- U8 dbbus_tx_data[3] = {0};
- U8 dbbus_rx_data[8] = {0};
-
- dbbus_tx_data[0] = 0x53;
- dbbus_tx_data[1] = 0x00;
- dbbus_tx_data[2] = 0x58;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4);
- mutex_unlock(&msg21xx_mutex);
- InfoAddr = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0];
- PoolAddr = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2];
- printk("InfoAddr=0x%X\n", InfoAddr);
- printk("PoolAddr=0x%X\n", PoolAddr);
-
- if ((InfoAddr != 0x0F) && (PoolAddr != 0x10))
- {
- msleep(10);
- dbbus_tx_data[0] = 0x53;
- dbbus_tx_data[1] = (InfoAddr >> 8) & 0xFF;
- dbbus_tx_data[2] = InfoAddr & 0xFF;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 8);
- mutex_unlock(&msg21xx_mutex);
-
- units = dbbus_rx_data[0];
- row = dbbus_rx_data[1];
- cnt = dbbus_rx_data[2];
- TransLen = (dbbus_rx_data[7]<<8) + dbbus_rx_data[6];
- printk("tpp: row=%d, units=%d\n", row, units);
- printk("tpp: cnt=%d, TransLen=%d\n", cnt, TransLen);
-
- // tpp
- if (device_create_file(firmware_cmd_dev, &dev_attr_tpp) < 0)
- {
- pr_err("Failed to create device file(%s)!\n", dev_attr_tpp.attr.name);
- }
- }
+ unsigned char dbbus_tx_data[3] = {0};
+ unsigned char dbbus_rx_data[8] = {0};
+
+ dbbus_tx_data[0] = 0x53;
+ dbbus_tx_data[1] = 0x00;
+ dbbus_tx_data[2] = 0x58;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 3);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4);
+ mutex_unlock(&msg21xx_mutex);
+ InfoAddr = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0];
+ PoolAddr = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2];
+
+ if ((InfoAddr != 0x0F) && (PoolAddr != 0x10)) {
+ msleep(20);
+ dbbus_tx_data[0] = 0x53;
+ dbbus_tx_data[1] = (InfoAddr >> 8) & 0xFF;
+ dbbus_tx_data[2] = InfoAddr & 0xFF;
+ mutex_lock(&msg21xx_mutex);
+ write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 3);
+ read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 8);
+ mutex_unlock(&msg21xx_mutex);
+
+ units = dbbus_rx_data[0];
+ row = dbbus_rx_data[1];
+ cnt = dbbus_rx_data[2];
+ TransLen = (dbbus_rx_data[7]<<8) + dbbus_rx_data[6];
+
+ if (device_create_file(firmware_cmd_dev, &dev_attr_tpp) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_tpp.attr.name);
+ }
+ }
}
#endif
-module_init(touch_driver_init);
-module_exit(touch_driver_exit);
MODULE_AUTHOR("MStar Semiconductor, Inc.");
MODULE_LICENSE("GPL v2");
-
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 55eff5ae04e4..c69927bd4ff2 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -386,6 +386,7 @@ struct arm_smmu_device {
unsigned int *irqs;
struct list_head list;
+ struct list_head static_cbndx_list;
struct rb_root masters;
int num_clocks;
@@ -491,6 +492,18 @@ static struct arm_smmu_option_prop arm_smmu_options[] = {
{ 0, NULL},
};
+#define TYPE_TRANS (S2CR_TYPE_TRANS >> S2CR_TYPE_SHIFT)
+#define TYPE_BYPASS (S2CR_TYPE_BYPASS >> S2CR_TYPE_SHIFT)
+#define TYPE_FAULT (S2CR_TYPE_FAULT >> S2CR_TYPE_SHIFT)
+
+struct static_cbndx_entry {
+ struct list_head list;
+ u8 cbndx;
+ u8 smr_idx;
+ u16 sid;
+ u8 type;
+};
+
static int arm_smmu_enable_clocks_atomic(struct arm_smmu_device *smmu);
static void arm_smmu_disable_clocks_atomic(struct arm_smmu_device *smmu);
static void arm_smmu_prepare_pgtable(void *addr, void *cookie);
@@ -767,11 +780,103 @@ static int __arm_smmu_alloc_bitmap(unsigned long *map, int start, int end)
return idx;
}
+static int __arm_smmu_set_bitmap(unsigned long *map, int idx)
+{
+ return test_and_set_bit(idx, map);
+}
+
+static struct static_cbndx_entry *arm_smmu_get_static_entry_from_sid(
+ struct arm_smmu_device *smmu, int sid)
+{
+ struct static_cbndx_entry *entry;
+
+ list_for_each_entry(entry, &smmu->static_cbndx_list, list) {
+ if (entry->sid == sid)
+ return entry;
+ }
+
+ return NULL;
+}
+
+static struct static_cbndx_entry *arm_smmu_get_static_entry_from_context(
+ struct arm_smmu_device *smmu, int idx)
+{
+ struct static_cbndx_entry *entry;
+
+ list_for_each_entry(entry, &smmu->static_cbndx_list, list) {
+ if (entry->type == TYPE_TRANS && entry->cbndx == idx)
+ return entry;
+ }
+
+ return NULL;
+}
+
+static struct static_cbndx_entry *arm_smmu_get_static_entry_from_smr(
+ struct arm_smmu_device *smmu, int idx)
+{
+ struct static_cbndx_entry *entry;
+
+ list_for_each_entry(entry, &smmu->static_cbndx_list, list) {
+ if (entry->smr_idx == idx)
+ return entry;
+ }
+
+ return NULL;
+}
+
+static int arm_smmu_alloc_smr_idx(struct arm_smmu_device *smmu, int start,
+ int end, int sid)
+{
+ struct static_cbndx_entry *entry = arm_smmu_get_static_entry_from_sid(
+ smmu, sid);
+
+ if (entry)
+ return entry->smr_idx;
+ else
+ return __arm_smmu_alloc_bitmap(smmu->smr_map, start, end);
+}
+
+static int arm_smmu_alloc_context_idx(struct arm_smmu_device *smmu, int start,
+ int end, u16 *streamids, int num_streamids)
+{
+ struct static_cbndx_entry *entry = NULL;
+ int i;
+
+ for (i = 0; i < num_streamids; ++i) {
+ entry = arm_smmu_get_static_entry_from_sid(smmu, streamids[i]);
+ if (entry && entry->type == TYPE_TRANS)
+ break;
+ }
+
+ if (entry && entry->type == TYPE_TRANS)
+ return entry->cbndx;
+ else
+ return __arm_smmu_alloc_bitmap(smmu->context_map, start, end);
+}
+
static void __arm_smmu_free_bitmap(unsigned long *map, int idx)
{
clear_bit(idx, map);
}
+static void arm_smmu_free_smr_idx(struct arm_smmu_device *smmu, int idx)
+{
+ struct static_cbndx_entry *entry = arm_smmu_get_static_entry_from_smr(
+ smmu, idx);
+
+ if (!entry)
+ __arm_smmu_free_bitmap(smmu->smr_map, idx);
+}
+
+static void arm_smmu_free_context_idx(struct arm_smmu_device *smmu, int idx)
+{
+ struct static_cbndx_entry *entry =
+ arm_smmu_get_static_entry_from_context(smmu, idx);
+
+ if (!entry)
+ __arm_smmu_free_bitmap(smmu->context_map, idx);
+}
+
static void arm_smmu_unprepare_clocks(struct arm_smmu_device *smmu)
{
int i;
@@ -1582,7 +1687,8 @@ static int arm_smmu_restore_sec_cfg(struct arm_smmu_device *smmu)
}
static int arm_smmu_init_domain_context(struct iommu_domain *domain,
- struct arm_smmu_device *smmu)
+ struct arm_smmu_device *smmu,
+ struct arm_smmu_master_cfg *master_cfg)
{
int irq, start, ret = 0;
unsigned long ias, oas;
@@ -1650,14 +1756,12 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
}
if (cfg->cbndx == INVALID_CBNDX) {
- ret = __arm_smmu_alloc_bitmap(smmu->context_map, start,
- smmu->num_context_banks);
+ ret = arm_smmu_alloc_context_idx(smmu, start,
+ smmu->num_context_banks, master_cfg->streamids,
+ master_cfg->num_streamids);
if (IS_ERR_VALUE(ret))
goto out;
cfg->cbndx = ret;
- } else {
- if (test_and_set_bit(cfg->cbndx, smmu->context_map))
- goto out;
}
if (smmu->version == ARM_SMMU_V1) {
@@ -1764,7 +1868,7 @@ free_irqs:
free_irq(irq, domain);
}
- __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
+ arm_smmu_free_context_idx(smmu, cfg->cbndx);
smmu_domain->smmu = NULL;
}
@@ -1847,8 +1951,8 @@ static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu,
/* Allocate the SMRs on the SMMU */
for (i = 0; i < cfg->num_streamids; ++i) {
- int idx = __arm_smmu_alloc_bitmap(smmu->smr_map, 0,
- smmu->num_mapping_groups);
+ int idx = arm_smmu_alloc_smr_idx(smmu, 0,
+ smmu->num_mapping_groups, cfg->streamids[i]);
if (IS_ERR_VALUE(idx)) {
dev_err(smmu->dev, "failed to allocate free SMR\n");
goto err_free_smrs;
@@ -1873,7 +1977,7 @@ static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu,
err_free_smrs:
while (--i >= 0)
- __arm_smmu_free_bitmap(smmu->smr_map, smrs[i].idx);
+ arm_smmu_free_smr_idx(smmu, smrs[i].idx);
kfree(smrs);
return -ENOSPC;
}
@@ -1893,7 +1997,7 @@ static void arm_smmu_master_free_smrs(struct arm_smmu_device *smmu,
u8 idx = smrs[i].idx;
writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(idx));
- __arm_smmu_free_bitmap(smmu->smr_map, idx);
+ arm_smmu_free_smr_idx(smmu, idx);
}
cfg->smrs = NULL;
@@ -2051,32 +2155,18 @@ out:
static int arm_smmu_populate_cb(struct arm_smmu_device *smmu,
struct arm_smmu_domain *smmu_domain, struct device *dev)
{
- void __iomem *gr0_base;
struct arm_smmu_master_cfg *cfg;
struct arm_smmu_cfg *smmu_cfg = &smmu_domain->cfg;
- int i;
- u32 sid;
+ struct static_cbndx_entry *entry;
- gr0_base = ARM_SMMU_GR0(smmu);
cfg = find_smmu_master_cfg(dev);
-
if (!cfg)
return -ENODEV;
- sid = cfg->streamids[0];
-
- for (i = 0; i < smmu->num_mapping_groups; i++) {
- u32 smr, s2cr;
- u8 cbndx;
-
- smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(i));
-
- if (sid == ((smr >> SMR_ID_SHIFT) & SMR_ID_MASK)) {
- s2cr = readl_relaxed(gr0_base + ARM_SMMU_GR0_S2CR(i));
- cbndx = (s2cr >> S2CR_CBNDX_SHIFT) & S2CR_CBNDX_MASK;
- smmu_cfg->cbndx = cbndx;
- return 0;
- }
+ entry = arm_smmu_get_static_entry_from_sid(smmu, cfg->streamids[0]);
+ if (entry && entry->type == TYPE_TRANS) {
+ smmu_cfg->cbndx = entry->cbndx;
+ return 0;
}
return -EINVAL;
@@ -2150,8 +2240,14 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
smmu_domain->slave_side_secure = true;
}
+ cfg = find_smmu_master_cfg(dev);
+ if (!cfg) {
+ ret = -ENODEV;
+ goto err_disable_clocks;
+ }
+
/* Ensure that the domain is finalised */
- ret = arm_smmu_init_domain_context(domain, smmu);
+ ret = arm_smmu_init_domain_context(domain, smmu, cfg);
if (IS_ERR_VALUE(ret))
goto err_disable_clocks;
@@ -2177,12 +2273,6 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
}
/* Looks ok, so add the device to the domain */
- cfg = find_smmu_master_cfg(dev);
- if (!cfg) {
- ret = -ENODEV;
- goto err_destroy_domain_context;
- }
-
ret = arm_smmu_domain_add_master(smmu_domain, cfg);
if (ret)
goto err_destroy_domain_context;
@@ -3603,6 +3693,62 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
return 0;
}
+static int arm_smmu_add_static_cbndx(struct arm_smmu_device *smmu, int sid,
+ int smr_idx)
+{
+ void __iomem *gr0_base;
+ u32 s2cr_reg;
+ struct static_cbndx_entry *entry;
+
+ entry = devm_kzalloc(smmu->dev, sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+
+ gr0_base = ARM_SMMU_GR0(smmu);
+ s2cr_reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_S2CR(smr_idx));
+ entry->type = (s2cr_reg >> S2CR_TYPE_SHIFT) & S2CR_TYPE_MASK;
+ entry->smr_idx = smr_idx;
+ entry->sid = sid;
+
+ if (entry->type == TYPE_TRANS) {
+ entry->cbndx = (s2cr_reg >> S2CR_CBNDX_SHIFT) &
+ S2CR_CBNDX_MASK;
+ __arm_smmu_set_bitmap(smmu->context_map, entry->cbndx);
+ pr_debug("Static context bank: smr:%d, sid:%d, cbndx:%d\n",
+ smr_idx, sid, entry->cbndx);
+ }
+ __arm_smmu_set_bitmap(smmu->smr_map, smr_idx);
+ list_add(&entry->list, &smmu->static_cbndx_list);
+
+ return 0;
+}
+
+static int arm_smmu_init_static_cbndx_list(struct arm_smmu_device *smmu)
+{
+ int i, ret = 0;
+ void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
+
+ for (i = 0; i < smmu->num_mapping_groups; ++i) {
+ u32 smr_reg, sid;
+
+ smr_reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(i));
+ if (smr_reg & SMR_VALID) {
+ u32 smr_mask = (smr_reg >> SMR_MASK_SHIFT) &
+ SMR_MASK_MASK;
+
+ if (smr_mask != 0)
+ dev_warn(smmu->dev,
+ "Static smr mask not supported\n");
+ sid = ((smr_reg >> SMR_ID_SHIFT) & SMR_ID_MASK);
+ ret = arm_smmu_add_static_cbndx(smmu, sid, i);
+ if (ret)
+ break;
+ }
+ }
+
+ return ret;
+}
+
static const struct of_device_id arm_smmu_of_match[] = {
{ .compatible = "arm,smmu-v1", .data = (void *)ARM_SMMU_V1 },
{ .compatible = "arm,smmu-v2", .data = (void *)ARM_SMMU_V2 },
@@ -3632,6 +3778,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
mutex_init(&smmu->attach_lock);
spin_lock_init(&smmu->atos_lock);
spin_lock_init(&smmu->clock_refs_lock);
+ INIT_LIST_HEAD(&smmu->static_cbndx_list);
of_id = of_match_node(arm_smmu_of_match, dev->of_node);
if (!of_id)
@@ -3713,6 +3860,9 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
smmu->sec_id = msm_dev_to_device_id(dev);
err = arm_smmu_device_cfg_probe(smmu);
+ if (!err)
+ err = arm_smmu_init_static_cbndx_list(smmu);
+
arm_smmu_disable_clocks(smmu);
if (err)
goto out_put_masters;
diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig
index 18ae7fa5454b..9c2697dde76d 100644
--- a/drivers/platform/msm/Kconfig
+++ b/drivers/platform/msm/Kconfig
@@ -114,7 +114,6 @@ config IPA3
Kernel and user-space processes can call the IPA driver
to configure IPA core.
-
config RMNET_IPA3
tristate "IPA3 RMNET WWAN Network Device"
depends on IPA3 && MSM_QMI_INTERFACE
@@ -124,6 +123,16 @@ config RMNET_IPA3
for RmNet Data Driver and also exchange of QMI messages between
A7 and Q6 IPA-driver.
+config IPA_UT
+ tristate "IPA Unit-Test Framework and Test Suites"
+ depends on IPA3 && DEBUG_FS
+ help
+ This Module implements IPA in-kernel test framework.
+ The framework supports defining and running tests, grouped
+ into suites according to the sub-unit of the IPA being tested.
+ The user interface to run and control the tests is debugfs file
+ system.
+
config SSM
tristate "QTI Secure Service Module"
depends on QSEECOM
diff --git a/drivers/platform/msm/ipa/Makefile b/drivers/platform/msm/ipa/Makefile
index 704dd0abfefa..15ed471f383c 100644
--- a/drivers/platform/msm/ipa/Makefile
+++ b/drivers/platform/msm/ipa/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_IPA) += ipa_v2/ ipa_clients/ ipa_common
obj-$(CONFIG_IPA3) += ipa_v3/ ipa_clients/ ipa_common
+obj-$(CONFIG_IPA_UT) += test/
ipa_common += ipa_api.o ipa_rm.o ipa_rm_dependency_graph.o ipa_rm_peers_list.o ipa_rm_resource.o ipa_rm_inactivity_timer.o
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index 09d1166e29a6..a08d157e2b0f 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -2533,6 +2533,50 @@ int ipa_stop_gsi_channel(u32 clnt_hdl)
}
EXPORT_SYMBOL(ipa_stop_gsi_channel);
+/**
+ * ipa_get_version_string() - Get string representation of IPA version
+ * @ver: IPA version
+ *
+ * Return: Constant string representation
+ */
+const char *ipa_get_version_string(enum ipa_hw_type ver)
+{
+ const char *str;
+
+ switch (ver) {
+ case IPA_HW_v1_0:
+ str = "1.0";
+ break;
+ case IPA_HW_v1_1:
+ str = "1.1";
+ break;
+ case IPA_HW_v2_0:
+ str = "2.0";
+ break;
+ case IPA_HW_v2_1:
+ str = "2.1";
+ break;
+ case IPA_HW_v2_5:
+ str = "2.5/2.6";
+ break;
+ case IPA_HW_v2_6L:
+ str = "2.6L";
+ break;
+ case IPA_HW_v3_0:
+ str = "3.0";
+ break;
+ case IPA_HW_v3_1:
+ str = "3.1";
+ break;
+ default:
+ str = "Invalid version";
+ break;
+ }
+
+ return str;
+}
+EXPORT_SYMBOL(ipa_get_version_string);
+
static struct of_device_id ipa_plat_drv_match[] = {
{ .compatible = "qcom,ipa", },
{ .compatible = "qcom,ipa-smmu-ap-cb", },
diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h
index 115348251d17..c5f75046cd2c 100644
--- a/drivers/platform/msm/ipa/ipa_common_i.h
+++ b/drivers/platform/msm/ipa/ipa_common_i.h
@@ -355,5 +355,6 @@ u8 *ipa_write_16(u16 hw, u8 *dest);
u8 *ipa_write_8(u8 b, u8 *dest);
u8 *ipa_pad_to_64(u8 *dest);
u8 *ipa_pad_to_32(u8 *dest);
+const char *ipa_get_version_string(enum ipa_hw_type ver);
#endif /* _IPA_COMMON_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index c3c5ae38ec14..95ef9afbbd3e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -2131,6 +2131,12 @@ void ipa3_debugfs_remove(void)
debugfs_remove_recursive(dent);
}
+struct dentry *ipa_debugfs_get_root(void)
+{
+ return dent;
+}
+EXPORT_SYMBOL(ipa_debugfs_get_root);
+
#else /* !CONFIG_DEBUG_FS */
void ipa3_debugfs_init(void) {}
void ipa3_debugfs_remove(void) {}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 806510ea8867..a7587b2b9675 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -2012,4 +2012,5 @@ int ipa3_smmu_map_peer_buff(u64 iova, phys_addr_t phys_addr,
u32 size, bool map);
int ipa3_ntn_init(void);
int ipa3_get_ntn_stats(struct Ipa3HwStatsNTNInfoData_t *stats);
+struct dentry *ipa_debugfs_get_root(void);
#endif /* _IPA3_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
index 6c4d14b093c3..bcd2cb3bfd7a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
@@ -535,6 +535,11 @@ static int ipahal_imm_cmd_init(enum ipa_hw_type ipa_hw_type)
IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
+ if ((ipa_hw_type < 0) || (ipa_hw_type >= IPA_HW_MAX)) {
+ IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
+ return -EINVAL;
+ }
+
memset(&zero_obj, 0, sizeof(zero_obj));
for (i = IPA_HW_v3_0 ; i < ipa_hw_type ; i++) {
for (j = 0; j < IPA_IMM_CMD_MAX ; j++) {
@@ -901,6 +906,11 @@ static int ipahal_pkt_status_init(enum ipa_hw_type ipa_hw_type)
IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
+ if ((ipa_hw_type < 0) || (ipa_hw_type >= IPA_HW_MAX)) {
+ IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
+ return -EINVAL;
+ }
+
/*
* Since structure alignment is implementation dependent,
* add test to avoid different and incompatible data layouts.
@@ -1269,6 +1279,12 @@ int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base,
goto bail_free_ctx;
}
+ if (ipa_hw_type >= IPA_HW_MAX) {
+ IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
+ result = -EINVAL;
+ goto bail_free_ctx;
+ }
+
if (!base) {
IPAHAL_ERR("invalid memory io mapping addr\n");
result = -EINVAL;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
index c47d353d9658..a3345d7ac305 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -1066,6 +1066,11 @@ int ipahal_reg_init(enum ipa_hw_type ipa_hw_type)
IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
+ if ((ipa_hw_type < 0) || (ipa_hw_type >= IPA_HW_MAX)) {
+ IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
+ return -EINVAL;
+ }
+
memset(&zero_obj, 0, sizeof(zero_obj));
for (i = IPA_HW_v3_0 ; i < ipa_hw_type ; i++) {
for (j = 0; j < IPA_REG_MAX ; j++) {
diff --git a/drivers/platform/msm/ipa/test/Makefile b/drivers/platform/msm/ipa/test/Makefile
new file mode 100644
index 000000000000..62bb9a783c89
--- /dev/null
+++ b/drivers/platform/msm/ipa/test/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_IPA_UT) += ipa_ut_mod.o
+ipa_ut_mod-y := ipa_ut_framework.o ipa_test_example.o
diff --git a/drivers/platform/msm/ipa/test/ipa_test_example.c b/drivers/platform/msm/ipa/test/ipa_test_example.c
new file mode 100644
index 000000000000..0313375ec3d3
--- /dev/null
+++ b/drivers/platform/msm/ipa/test/ipa_test_example.c
@@ -0,0 +1,99 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include "ipa_ut_framework.h"
+
+/**
+ * Example IPA Unit-test suite
+ * To be a reference for writing new suites and tests.
+ * This suite is also used as unit-test for the testing framework itself.
+ * Structure:
+ * 1- Define the setup and teardown functions
+ * Not Mandatory. Null may be used as well
+ * 2- For each test, define its Run() function
+ * 3- Use IPA_UT_DEFINE_SUITE_START() to start defining the suite
+ * 4- use IPA_UT_ADD_TEST() for adding tests within
+ * the suite definition block
+ * 5- IPA_UT_DEFINE_SUITE_END() close the suite definition
+ */
+
+static int ipa_test_example_dummy;
+
+static int ipa_test_example_suite_setup(void **ppriv)
+{
+ IPA_UT_DBG("Start Setup - set 0x1234F\n");
+
+ ipa_test_example_dummy = 0x1234F;
+ *ppriv = (void *)&ipa_test_example_dummy;
+
+ return 0;
+}
+
+static int ipa_test_example_teardown(void *priv)
+{
+ IPA_UT_DBG("Start Teardown\n");
+ IPA_UT_DBG("priv=0x%p - value=0x%x\n", priv, *((int *)priv));
+
+ return 0;
+}
+
+static int ipa_test_example_test1(void *priv)
+{
+ IPA_UT_LOG("priv=0x%p - value=0x%x\n", priv, *((int *)priv));
+ ipa_test_example_dummy++;
+
+ return 0;
+}
+
+static int ipa_test_example_test2(void *priv)
+{
+ IPA_UT_LOG("priv=0x%p - value=0x%x\n", priv, *((int *)priv));
+ ipa_test_example_dummy++;
+
+ return 0;
+}
+
+static int ipa_test_example_test3(void *priv)
+{
+ IPA_UT_LOG("priv=0x%p - value=0x%x\n", priv, *((int *)priv));
+ ipa_test_example_dummy++;
+
+ return 0;
+}
+
+static int ipa_test_example_test4(void *priv)
+{
+ IPA_UT_LOG("priv=0x%p - value=0x%x\n", priv, *((int *)priv));
+ ipa_test_example_dummy++;
+
+ IPA_UT_TEST_FAIL_REPORT("failed on test");
+
+ return -EFAULT;
+}
+
+/* Suite definition block */
+IPA_UT_DEFINE_SUITE_START(example, "Example suite",
+ ipa_test_example_suite_setup, ipa_test_example_teardown)
+{
+ IPA_UT_ADD_TEST(test1, "This is test number 1",
+ ipa_test_example_test1, false, IPA_HW_v1_0, IPA_HW_MAX),
+
+ IPA_UT_ADD_TEST(test2, "This is test number 2",
+ ipa_test_example_test2, false, IPA_HW_v1_0, IPA_HW_MAX),
+
+ IPA_UT_ADD_TEST(test3, "This is test number 3",
+ ipa_test_example_test3, false, IPA_HW_v1_1, IPA_HW_v2_6),
+
+ IPA_UT_ADD_TEST(test4, "This is test number 4",
+ ipa_test_example_test4, false, IPA_HW_v1_1, IPA_HW_MAX),
+
+} IPA_UT_DEFINE_SUITE_END(example);
diff --git a/drivers/platform/msm/ipa/test/ipa_ut_framework.c b/drivers/platform/msm/ipa/test/ipa_ut_framework.c
new file mode 100644
index 000000000000..8816fc37c2e2
--- /dev/null
+++ b/drivers/platform/msm/ipa/test/ipa_ut_framework.c
@@ -0,0 +1,969 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/ipa.h>
+#include "../ipa_v3/ipa_i.h"
+#include "ipa_ut_framework.h"
+#include "ipa_ut_suite_list.h"
+#include "ipa_ut_i.h"
+
+
+#define IPA_UT_DEBUG_WRITE_BUF_SIZE 256
+#define IPA_UT_DEBUG_READ_BUF_SIZE 1024
+
+#define IPA_UT_READ_WRITE_DBG_FILE_MODE \
+ (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP)
+
+/**
+ * struct ipa_ut_context - I/S context
+ * @inited: Will wait till IPA is ready. Will create the enable file
+ * @enabled: All tests and suite debugfs files are created
+ * @lock: Lock for mutual exclustion
+ * @ipa_dbgfs_root: IPA root debugfs folder
+ * @test_dbgfs_root: UT root debugfs folder. Sub-folder of IPA root
+ * @test_dbgfs_suites: Suites root debugfs folder. Sub-folder of UT root
+ */
+struct ipa_ut_context {
+ bool inited;
+ bool enabled;
+ struct mutex lock;
+ struct dentry *ipa_dbgfs_root;
+ struct dentry *test_dbgfs_root;
+ struct dentry *test_dbgfs_suites;
+};
+
+static ssize_t ipa_ut_dbgfs_enable_read(struct file *file,
+ char __user *ubuf, size_t count, loff_t *ppos);
+static ssize_t ipa_ut_dbgfs_enable_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos);
+static ssize_t ipa_ut_dbgfs_test_read(struct file *file,
+ char __user *ubuf, size_t count, loff_t *ppos);
+static ssize_t ipa_ut_dbgfs_test_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos);
+static int ipa_ut_dbgfs_all_test_open(struct inode *inode,
+ struct file *filp);
+static int ipa_ut_dbgfs_regression_test_open(struct inode *inode,
+ struct file *filp);
+static ssize_t ipa_ut_dbgfs_meta_test_read(struct file *file,
+ char __user *ubuf, size_t count, loff_t *ppos);
+static ssize_t ipa_ut_dbgfs_meta_test_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos);
+
+
+static const struct file_operations ipa_ut_dbgfs_enable_fops = {
+ .read = ipa_ut_dbgfs_enable_read,
+ .write = ipa_ut_dbgfs_enable_write,
+};
+static const struct file_operations ipa_ut_dbgfs_test_fops = {
+ .read = ipa_ut_dbgfs_test_read,
+ .write = ipa_ut_dbgfs_test_write,
+};
+static const struct file_operations ipa_ut_dbgfs_all_test_fops = {
+ .open = ipa_ut_dbgfs_all_test_open,
+ .read = ipa_ut_dbgfs_meta_test_read,
+ .write = ipa_ut_dbgfs_meta_test_write,
+};
+static const struct file_operations ipa_ut_dbgfs_regression_test_fops = {
+ .open = ipa_ut_dbgfs_regression_test_open,
+ .read = ipa_ut_dbgfs_meta_test_read,
+ .write = ipa_ut_dbgfs_meta_test_write,
+};
+
+static struct ipa_ut_context *ipa_ut_ctx;
+char *_IPA_UT_TEST_LOG_BUF_NAME;
+struct ipa_ut_tst_fail_report _IPA_UT_TEST_FAIL_REPORT_DATA;
+
+
+/**
+ * ipa_ut_show_suite_exec_summary() - Show tests run summary
+ * @suite: suite to print its running summary
+ *
+ * Print list of succeeded tests, failed tests and skipped tests
+ *
+ * Note: Assumes lock acquired
+ */
+static void ipa_ut_show_suite_exec_summary(const struct ipa_ut_suite *suite)
+{
+ int i;
+
+ IPA_UT_DBG("Entry\n");
+
+ ipa_assert_on(!suite);
+
+ pr_info("\n\n");
+ pr_info("\t Suite '%s' summary\n", suite->meta_data->name);
+ pr_info("===========================\n");
+ pr_info("Successful tests\n");
+ pr_info("----------------\n");
+ for (i = 0 ; i < suite->tests_cnt ; i++) {
+ if (suite->tests[i].res != IPA_UT_TEST_RES_SUCCESS)
+ continue;
+ pr_info("\t%s\n", suite->tests[i].name);
+ }
+ pr_info("\nFailed tests\n");
+ pr_info("------------\n");
+ for (i = 0 ; i < suite->tests_cnt ; i++) {
+ if (suite->tests[i].res != IPA_UT_TEST_RES_FAIL)
+ continue;
+ pr_info("\t%s\n", suite->tests[i].name);
+ }
+ pr_info("\nSkipped tests\n");
+ pr_info("-------------\n");
+ for (i = 0 ; i < suite->tests_cnt ; i++) {
+ if (suite->tests[i].res != IPA_UT_TEST_RES_SKIP)
+ continue;
+ pr_info("\t%s\n", suite->tests[i].name);
+ }
+ pr_info("\n");
+}
+
+/**
+ * ipa_ut_dbgfs_meta_test_write() - Debugfs write func for a for a meta test
+ * @params: write fops
+ *
+ * Used to run all/regression tests in a suite
+ * Create log buffer that the test can use to store ongoing logs
+ * IPA clocks need to be voted.
+ * Run setup() once before running the tests and teardown() once after
+ * If no such call-backs then ignore it; if failed then fail the suite
+ * Print tests progress during running
+ * Test log and fail report will be showed only if the test failed.
+ * Finally show Summary of the suite tests running
+ *
+ * Note: If test supported IPA H/W version mismatch, skip it
+ * If a test lack run function, skip it
+ * If test doesn't belong to regression and it is regression run, skip it
+ * Note: Running mode: Do not stop running on failure
+ *
+ * Return: Negative in failure, given characters amount in success
+ */
+static ssize_t ipa_ut_dbgfs_meta_test_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos)
+{
+ struct ipa_ut_suite *suite;
+ int i;
+ enum ipa_hw_type ipa_ver;
+ int rc = 0;
+ long meta_type;
+ bool tst_fail = false;
+
+ IPA_UT_DBG("Entry\n");
+
+ mutex_lock(&ipa_ut_ctx->lock);
+ suite = file->f_inode->i_private;
+ ipa_assert_on(!suite);
+ meta_type = (long)(file->private_data);
+ IPA_UT_DBG("Meta test type %ld\n", meta_type);
+
+ _IPA_UT_TEST_LOG_BUF_NAME = kzalloc(_IPA_UT_TEST_LOG_BUF_SIZE,
+ GFP_KERNEL);
+ if (!_IPA_UT_TEST_LOG_BUF_NAME) {
+ IPA_UT_ERR("failed to allocate %d bytes\n",
+ _IPA_UT_TEST_LOG_BUF_SIZE);
+ rc = -ENOMEM;
+ goto unlock_mutex;
+ }
+
+ if (!suite->tests_cnt || !suite->tests) {
+ pr_info("No tests for suite '%s'\n", suite->meta_data->name);
+ goto free_mem;
+ }
+
+ ipa_ver = ipa_get_hw_type();
+
+ IPA_ACTIVE_CLIENTS_INC_SPECIAL("IPA_UT");
+
+ if (suite->meta_data->setup) {
+ pr_info("*** Suite '%s': Run setup ***\n",
+ suite->meta_data->name);
+ rc = suite->meta_data->setup(&suite->meta_data->priv);
+ if (rc) {
+ IPA_UT_ERR("Setup failed for suite %s\n",
+ suite->meta_data->name);
+ rc = -EFAULT;
+ goto release_clock;
+ }
+ } else {
+ pr_info("*** Suite '%s': No Setup ***\n",
+ suite->meta_data->name);
+ }
+
+ pr_info("*** Suite '%s': Run %s tests ***\n\n",
+ suite->meta_data->name,
+ meta_type == IPA_UT_META_TEST_REGRESSION ? "regression" : "all"
+ );
+ for (i = 0 ; i < suite->tests_cnt ; i++) {
+ if (meta_type == IPA_UT_META_TEST_REGRESSION &&
+ !suite->tests[i].run_in_regression) {
+ pr_info(
+ "*** Test '%s': Skip - Not in regression ***\n\n"
+ , suite->tests[i].name);
+ suite->tests[i].res = IPA_UT_TEST_RES_SKIP;
+ continue;
+ }
+ if (suite->tests[i].min_ipa_hw_ver > ipa_ver ||
+ suite->tests[i].max_ipa_hw_ver < ipa_ver) {
+ pr_info(
+ "*** Test '%s': Skip - IPA VER mismatch ***\n\n"
+ , suite->tests[i].name);
+ suite->tests[i].res = IPA_UT_TEST_RES_SKIP;
+ continue;
+ }
+ if (!suite->tests[i].run) {
+ pr_info(
+ "*** Test '%s': Skip - No Run function ***\n\n"
+ , suite->tests[i].name);
+ suite->tests[i].res = IPA_UT_TEST_RES_SKIP;
+ continue;
+ }
+
+ _IPA_UT_TEST_LOG_BUF_NAME[0] = '\0';
+ _IPA_UT_TEST_FAIL_REPORT_DATA.valid = false;
+ pr_info("*** Test '%s': Running... ***\n",
+ suite->tests[i].name);
+ rc = suite->tests[i].run(suite->meta_data->priv);
+ if (rc) {
+ tst_fail = true;
+ suite->tests[i].res = IPA_UT_TEST_RES_FAIL;
+ pr_info("%s", _IPA_UT_TEST_LOG_BUF_NAME);
+ } else {
+ suite->tests[i].res = IPA_UT_TEST_RES_SUCCESS;
+ }
+
+ pr_info(">>>>>>**** TEST '%s': %s ****<<<<<<\n",
+ suite->tests[i].name, tst_fail ? "FAIL" : "SUCCESS");
+
+ if (tst_fail && _IPA_UT_TEST_FAIL_REPORT_DATA.valid) {
+ pr_info("*** FAIL INFO:\n");
+ pr_info("\tFILE = %s\n\tFUNC = %s()\n\tLINE = %d\n",
+ _IPA_UT_TEST_FAIL_REPORT_DATA.file,
+ _IPA_UT_TEST_FAIL_REPORT_DATA.func,
+ _IPA_UT_TEST_FAIL_REPORT_DATA.line);
+ pr_info("\t%s\n", _IPA_UT_TEST_FAIL_REPORT_DATA.info);
+ }
+
+ pr_info("\n");
+ }
+
+ if (suite->meta_data->teardown) {
+ pr_info("*** Suite '%s': Run Teardown ***\n",
+ suite->meta_data->name);
+ rc = suite->meta_data->teardown(suite->meta_data->priv);
+ if (rc) {
+ IPA_UT_ERR("Teardown failed for suite %s\n",
+ suite->meta_data->name);
+ rc = -EFAULT;
+ goto release_clock;
+ }
+ } else {
+ pr_info("*** Suite '%s': No Teardown ***\n",
+ suite->meta_data->name);
+ }
+
+ ipa_ut_show_suite_exec_summary(suite);
+
+release_clock:
+ IPA_ACTIVE_CLIENTS_DEC_SPECIAL("IPA_UT");
+free_mem:
+ kfree(_IPA_UT_TEST_LOG_BUF_NAME);
+unlock_mutex:
+ mutex_unlock(&ipa_ut_ctx->lock);
+ return ((!rc && !tst_fail) ? count : -EFAULT);
+}
+
+/**
+ * ipa_ut_dbgfs_meta_test_read() - Debugfs read func for a meta test
+ * @params: read fops
+ *
+ * Meta test, is a test that describes other test or bunch of tests.
+ * for example, the 'all' test. Running this test will run all
+ * the tests in the suite.
+ *
+ * Show information regard the suite. E.g. name and description
+ * If regression - List the regression tests names
+ *
+ * Return: Amount of characters written to user space buffer
+ */
+static ssize_t ipa_ut_dbgfs_meta_test_read(struct file *file,
+ char __user *ubuf, size_t count, loff_t *ppos)
+{
+ char *buf;
+ struct ipa_ut_suite *suite;
+ int nbytes;
+ ssize_t cnt;
+ long meta_type;
+ int i;
+
+ IPA_UT_DBG("Entry\n");
+
+ mutex_lock(&ipa_ut_ctx->lock);
+ suite = file->f_inode->i_private;
+ ipa_assert_on(!suite);
+ meta_type = (long)(file->private_data);
+ IPA_UT_DBG("Meta test type %ld\n", meta_type);
+
+ buf = kmalloc(IPA_UT_DEBUG_READ_BUF_SIZE, GFP_KERNEL);
+ if (!buf) {
+ IPA_UT_ERR("failed to allocate %d bytes\n",
+ IPA_UT_DEBUG_READ_BUF_SIZE);
+ cnt = 0;
+ goto unlock_mutex;
+ }
+
+ if (meta_type == IPA_UT_META_TEST_ALL) {
+ nbytes = scnprintf(buf, IPA_UT_DEBUG_READ_BUF_SIZE,
+ "\tMeta-test running all the tests in the suite:\n"
+ "\tSuite Name: %s\n"
+ "\tDescription: %s\n"
+ "\tNumber of test in suite: %zu\n",
+ suite->meta_data->name,
+ suite->meta_data->desc ?: "",
+ suite->tests_cnt);
+ } else {
+ nbytes = scnprintf(buf, IPA_UT_DEBUG_READ_BUF_SIZE,
+ "\tMeta-test running regression tests in the suite:\n"
+ "\tSuite Name: %s\n"
+ "\tDescription: %s\n"
+ "\tRegression tests:\n",
+ suite->meta_data->name,
+ suite->meta_data->desc ?: "");
+ for (i = 0 ; i < suite->tests_cnt ; i++) {
+ if (!suite->tests[i].run_in_regression)
+ continue;
+ nbytes += scnprintf(buf + nbytes,
+ IPA_UT_DEBUG_READ_BUF_SIZE - nbytes,
+ "\t\t%s\n", suite->tests[i].name);
+ }
+ }
+
+ cnt = simple_read_from_buffer(ubuf, count, ppos, buf, nbytes);
+ kfree(buf);
+
+unlock_mutex:
+ mutex_unlock(&ipa_ut_ctx->lock);
+ return cnt;
+}
+
+/**
+ * ipa_ut_dbgfs_regression_test_open() - Debugfs open function for
+ * 'regression' tests
+ * @params: open fops
+ *
+ * Mark "Regression tests" for meta-tests later operations.
+ *
+ * Return: Zero (always success).
+ */
+static int ipa_ut_dbgfs_regression_test_open(struct inode *inode,
+ struct file *filp)
+{
+ IPA_UT_DBG("Entry\n");
+
+ filp->private_data = (void *)(IPA_UT_META_TEST_REGRESSION);
+
+ return 0;
+}
+
+/**
+ * ipa_ut_dbgfs_all_test_open() - Debugfs open function for 'all' tests
+ * @params: open fops
+ *
+ * Mark "All tests" for meta-tests later operations.
+ *
+ * Return: Zero (always success).
+ */
+static int ipa_ut_dbgfs_all_test_open(struct inode *inode,
+ struct file *filp)
+{
+ IPA_UT_DBG("Entry\n");
+
+ filp->private_data = (void *)(IPA_UT_META_TEST_ALL);
+
+ return 0;
+}
+
+/**
+ * ipa_ut_dbgfs_test_write() - Debugfs write function for a test
+ * @params: write fops
+ *
+ * Used to run a test.
+ * Create log buffer that the test can use to store ongoing logs
+ * IPA clocks need to be voted.
+ * Run setup() before the test and teardown() after the tests.
+ * If no such call-backs then ignore it; if failed then fail the test
+ * If all succeeds, no printing to user
+ * If failed, test logs and failure report will be printed to user
+ *
+ * Note: Test must has run function and it's supported IPA H/W version
+ * must be matching. Otherwise test will fail.
+ *
+ * Return: Negative in failure, given characters amount in success
+ */
+static ssize_t ipa_ut_dbgfs_test_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos)
+{
+ struct ipa_ut_test *test;
+ struct ipa_ut_suite *suite;
+ bool tst_fail = false;
+ int rc = 0;
+ enum ipa_hw_type ipa_ver;
+
+ IPA_UT_DBG("Entry\n");
+
+ mutex_lock(&ipa_ut_ctx->lock);
+ test = file->f_inode->i_private;
+ ipa_assert_on(!test);
+
+ _IPA_UT_TEST_LOG_BUF_NAME = kzalloc(_IPA_UT_TEST_LOG_BUF_SIZE,
+ GFP_KERNEL);
+ if (!_IPA_UT_TEST_LOG_BUF_NAME) {
+ IPA_UT_ERR("failed to allocate %d bytes\n",
+ _IPA_UT_TEST_LOG_BUF_SIZE);
+ rc = -ENOMEM;
+ goto unlock_mutex;
+ }
+
+ if (!test->run) {
+ IPA_UT_ERR("*** Test %s - No run func ***\n",
+ test->name);
+ rc = -EFAULT;
+ goto free_mem;
+ }
+
+ ipa_ver = ipa_get_hw_type();
+ if (test->min_ipa_hw_ver > ipa_ver ||
+ test->max_ipa_hw_ver < ipa_ver) {
+ IPA_UT_ERR("Cannot run test %s on IPA HW Ver %s\n",
+ test->name, ipa_get_version_string(ipa_ver));
+ rc = -EFAULT;
+ goto free_mem;
+ }
+
+ IPA_ACTIVE_CLIENTS_INC_SPECIAL("IPA_UT");
+
+ suite = test->suite;
+ if (suite && suite->meta_data->setup) {
+ IPA_UT_DBG("*** Suite '%s': Run setup ***\n",
+ suite->meta_data->name);
+ rc = suite->meta_data->setup(&suite->meta_data->priv);
+ if (rc) {
+ IPA_UT_ERR("Setup failed for suite %s\n",
+ suite->meta_data->name);
+ rc = -EFAULT;
+ goto release_clock;
+ }
+ } else {
+ IPA_UT_DBG("*** Suite '%s': No Setup ***\n",
+ suite->meta_data->name);
+ }
+
+ IPA_UT_DBG("*** Test '%s': Running... ***\n", test->name);
+ _IPA_UT_TEST_FAIL_REPORT_DATA.valid = false;
+ rc = test->run(suite->meta_data->priv);
+ if (rc)
+ tst_fail = true;
+ IPA_UT_DBG("*** Test %s - ***\n", tst_fail ? "FAIL" : "SUCCESS");
+ if (tst_fail) {
+ pr_info("=================>>>>>>>>>>>\n");
+ pr_info("%s\n", _IPA_UT_TEST_LOG_BUF_NAME);
+ pr_info("**** TEST %s FAILED ****\n", test->name);
+ if (_IPA_UT_TEST_FAIL_REPORT_DATA.valid) {
+ pr_info("*** FAIL INFO:\n");
+ pr_info("\tFILE = %s\n\tFUNC = %s()\n\tLINE = %d\n",
+ _IPA_UT_TEST_FAIL_REPORT_DATA.file,
+ _IPA_UT_TEST_FAIL_REPORT_DATA.func,
+ _IPA_UT_TEST_FAIL_REPORT_DATA.line);
+ pr_info("\t%s\n", _IPA_UT_TEST_FAIL_REPORT_DATA.info);
+ }
+ pr_info("<<<<<<<<<<<=================\n");
+ }
+
+ if (suite && suite->meta_data->teardown) {
+ IPA_UT_DBG("*** Suite '%s': Run Teardown ***\n",
+ suite->meta_data->name);
+ rc = suite->meta_data->teardown(suite->meta_data->priv);
+ if (rc) {
+ IPA_UT_ERR("Teardown failed for suite %s\n",
+ suite->meta_data->name);
+ rc = -EFAULT;
+ goto release_clock;
+ }
+ } else {
+ IPA_UT_DBG("*** Suite '%s': No Teardown ***\n",
+ suite->meta_data->name);
+ }
+
+release_clock:
+ IPA_ACTIVE_CLIENTS_DEC_SPECIAL("IPA_UT");
+free_mem:
+ kfree(_IPA_UT_TEST_LOG_BUF_NAME);
+unlock_mutex:
+ mutex_unlock(&ipa_ut_ctx->lock);
+ return ((!rc && !tst_fail) ? count : -EFAULT);
+}
+
+/**
+ * ipa_ut_dbgfs_test_read() - Debugfs read function for a test
+ * @params: read fops
+ *
+ * print information regard the test. E.g. name and description
+ *
+ * Return: Amount of characters written to user space buffer
+ */
+static ssize_t ipa_ut_dbgfs_test_read(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char *buf;
+ struct ipa_ut_test *test;
+ int nbytes;
+ ssize_t cnt;
+
+ IPA_UT_DBG("Entry\n");
+
+ mutex_lock(&ipa_ut_ctx->lock);
+ test = file->f_inode->i_private;
+ ipa_assert_on(!test);
+
+ buf = kmalloc(IPA_UT_DEBUG_READ_BUF_SIZE, GFP_KERNEL);
+ if (!buf) {
+ IPA_UT_ERR("failed to allocate %d bytes\n",
+ IPA_UT_DEBUG_READ_BUF_SIZE);
+ cnt = 0;
+ goto unlock_mutex;
+ }
+
+ nbytes = scnprintf(buf, IPA_UT_DEBUG_READ_BUF_SIZE,
+ "\t Test Name: %s\n"
+ "\t Description: %s\n"
+ "\t Suite Name: %s\n"
+ "\t Run In Regression: %s\n"
+ "\t Supported IPA versions: [%s -> %s]\n",
+ test->name, test->desc ?: "", test->suite->meta_data->name,
+ test->run_in_regression ? "Yes" : "No",
+ ipa_get_version_string(test->min_ipa_hw_ver),
+ test->max_ipa_hw_ver == IPA_HW_MAX ? "MAX" :
+ ipa_get_version_string(test->max_ipa_hw_ver));
+
+ if (nbytes > count)
+ IPA_UT_ERR("User buf too small - return partial info\n");
+
+ cnt = simple_read_from_buffer(ubuf, count, ppos, buf, nbytes);
+ kfree(buf);
+
+unlock_mutex:
+ mutex_unlock(&ipa_ut_ctx->lock);
+ return cnt;
+}
+
+/**
+ * ipa_ut_framework_load_suites() - Load tests and expose them to user space
+ *
+ * Creates debugfs folder for each suite and then file for each test in it.
+ * Create debugfs "all" file for each suite for meta-test to run all tests.
+ *
+ * Note: Assumes lock acquired
+ *
+ * Return: Zero in success, otherwise in failure
+ */
+int ipa_ut_framework_load_suites(void)
+{
+ int suite_idx;
+ int tst_idx;
+ struct ipa_ut_suite *suite;
+ struct dentry *s_dent;
+ struct dentry *f_dent;
+
+ IPA_UT_DBG("Entry\n");
+
+ for (suite_idx = IPA_UT_SUITE_FIRST_INDEX;
+ suite_idx < IPA_UT_SUITES_COUNT; suite_idx++) {
+ suite = IPA_UT_GET_SUITE(suite_idx);
+
+ if (!suite->meta_data->name) {
+ IPA_UT_ERR("No suite name\n");
+ return -EFAULT;
+ }
+
+ s_dent = debugfs_create_dir(suite->meta_data->name,
+ ipa_ut_ctx->test_dbgfs_suites);
+
+ if (!s_dent || IS_ERR(s_dent)) {
+ IPA_UT_ERR("fail create dbg entry - suite %s\n",
+ suite->meta_data->name);
+ return -EFAULT;
+ }
+
+ for (tst_idx = 0; tst_idx < suite->tests_cnt ; tst_idx++) {
+ if (!suite->tests[tst_idx].name) {
+ IPA_UT_ERR("No test name on suite %s\n",
+ suite->meta_data->name);
+ return -EFAULT;
+ }
+ f_dent = debugfs_create_file(
+ suite->tests[tst_idx].name,
+ IPA_UT_READ_WRITE_DBG_FILE_MODE, s_dent,
+ &suite->tests[tst_idx],
+ &ipa_ut_dbgfs_test_fops);
+ if (!f_dent || IS_ERR(f_dent)) {
+ IPA_UT_ERR("fail create dbg entry - tst %s\n",
+ suite->tests[tst_idx].name);
+ return -EFAULT;
+ }
+ }
+
+ /* entry for meta-test all to run all tests in suites */
+ f_dent = debugfs_create_file(_IPA_UT_RUN_ALL_TEST_NAME,
+ IPA_UT_READ_WRITE_DBG_FILE_MODE, s_dent,
+ suite, &ipa_ut_dbgfs_all_test_fops);
+ if (!f_dent || IS_ERR(f_dent)) {
+ IPA_UT_ERR("fail to create dbg entry - %s\n",
+ _IPA_UT_RUN_ALL_TEST_NAME);
+ return -EFAULT;
+ }
+
+ /*
+ * entry for meta-test regression to run all regression
+ * tests in suites
+ */
+ f_dent = debugfs_create_file(_IPA_UT_RUN_REGRESSION_TEST_NAME,
+ IPA_UT_READ_WRITE_DBG_FILE_MODE, s_dent,
+ suite, &ipa_ut_dbgfs_regression_test_fops);
+ if (!f_dent || IS_ERR(f_dent)) {
+ IPA_UT_ERR("fail to create dbg entry - %s\n",
+ _IPA_UT_RUN_ALL_TEST_NAME);
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * ipa_ut_framework_enable() - Enable the framework
+ *
+ * Creates the tests and suites debugfs entries and load them.
+ * This will expose the tests to user space.
+ *
+ * Return: Zero in success, otherwise in failure
+ */
+static int ipa_ut_framework_enable(void)
+{
+ int ret = 0;
+
+ IPA_UT_DBG("Entry\n");
+
+ mutex_lock(&ipa_ut_ctx->lock);
+
+ if (ipa_ut_ctx->enabled) {
+ IPA_UT_ERR("Already enabled\n");
+ goto unlock_mutex;
+ }
+
+ ipa_ut_ctx->test_dbgfs_suites = debugfs_create_dir("suites",
+ ipa_ut_ctx->test_dbgfs_root);
+ if (!ipa_ut_ctx->test_dbgfs_suites ||
+ IS_ERR(ipa_ut_ctx->test_dbgfs_suites)) {
+ IPA_UT_ERR("failed to create suites debugfs dir\n");
+ ret = -EFAULT;
+ goto unlock_mutex;
+ }
+
+ if (ipa_ut_framework_load_suites()) {
+ IPA_UT_ERR("failed to load the suites into debugfs\n");
+ ret = -EFAULT;
+ goto fail_clean_suites_dbgfs;
+ }
+
+ ipa_ut_ctx->enabled = true;
+ goto unlock_mutex;
+
+fail_clean_suites_dbgfs:
+ debugfs_remove_recursive(ipa_ut_ctx->test_dbgfs_suites);
+unlock_mutex:
+ mutex_unlock(&ipa_ut_ctx->lock);
+ return ret;
+}
+
+/**
+ * ipa_ut_framework_disable() - Disable the framework
+ *
+ * Remove the tests and suites debugfs exposure.
+ *
+ * Return: Zero in success, otherwise in failure
+ */
+static int ipa_ut_framework_disable(void)
+{
+ int ret = 0;
+
+ IPA_UT_DBG("Entry\n");
+
+ mutex_lock(&ipa_ut_ctx->lock);
+
+ if (!ipa_ut_ctx->enabled) {
+ IPA_UT_ERR("Already disabled\n");
+ goto unlock_mutex;
+ }
+
+ debugfs_remove_recursive(ipa_ut_ctx->test_dbgfs_suites);
+
+ ipa_ut_ctx->enabled = false;
+
+unlock_mutex:
+ mutex_unlock(&ipa_ut_ctx->lock);
+ return ret;
+}
+
+/**
+ * ipa_ut_dbgfs_enable_write() - Debugfs enable file write fops
+ * @params: write fops
+ *
+ * Input should be number. If 0, then disable. Otherwise enable.
+ *
+ * Return: if failed then negative value, if succeeds, amount of given chars
+ */
+static ssize_t ipa_ut_dbgfs_enable_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos)
+{
+ char lcl_buf[IPA_UT_DEBUG_WRITE_BUF_SIZE];
+ s8 option = 0;
+ int ret;
+
+ IPA_UT_DBG("Entry\n");
+
+ if (sizeof(lcl_buf) < count + 1) {
+ IPA_UT_ERR("No enough space\n");
+ return -E2BIG;
+ }
+
+ if (copy_from_user(lcl_buf, buf, count)) {
+ IPA_UT_ERR("fail to copy buf from user space\n");
+ return -EFAULT;
+ }
+
+ lcl_buf[count] = '\0';
+ if (kstrtos8(lcl_buf, 0, &option)) {
+ IPA_UT_ERR("fail convert str to s8\n");
+ return -EINVAL;
+ }
+
+ if (option == 0)
+ ret = ipa_ut_framework_disable();
+ else
+ ret = ipa_ut_framework_enable();
+
+ return ret ?: count;
+}
+
+/**
+ * ipa_ut_dbgfs_enable_read() - Debugfs enable file read fops
+ * @params: read fops
+ *
+ * To show to user space if the I/S is enabled or disabled.
+ *
+ * Return: amount of characters returned to user space
+ */
+static ssize_t ipa_ut_dbgfs_enable_read(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ const char *status;
+
+ IPA_UT_DBG("Entry\n");
+
+ mutex_lock(&ipa_ut_ctx->lock);
+ status = ipa_ut_ctx->enabled ?
+ "Enabled - Write 0 to disable\n" :
+ "Disabled - Write 1 to enable\n";
+ mutex_unlock(&ipa_ut_ctx->lock);
+ return simple_read_from_buffer(ubuf, count, ppos,
+ status, strlen(status));
+}
+
+/**
+ * ipa_ut_framework_init() - Unit-tests framework initialization
+ *
+ * Complete tests initialization: Each tests needs to point to it's
+ * corresponing suite.
+ * Creates the framework debugfs root directory under IPA directory.
+ * Create enable debugfs file - to enable/disable the framework.
+ *
+ * Return: Zero in success, otherwise in failure
+ */
+static int ipa_ut_framework_init(void)
+{
+ struct dentry *dfile_enable;
+ int ret;
+ int suite_idx;
+ int test_idx;
+ struct ipa_ut_suite *suite;
+
+ IPA_UT_DBG("Entry\n");
+
+ ipa_assert_on(!ipa_ut_ctx);
+
+ ipa_ut_ctx->ipa_dbgfs_root = ipa_debugfs_get_root();
+ if (!ipa_ut_ctx->ipa_dbgfs_root) {
+ IPA_UT_ERR("No IPA debugfs root entry\n");
+ return -EFAULT;
+ }
+
+ mutex_lock(&ipa_ut_ctx->lock);
+
+ /* tests needs to point to their corresponding suites structures */
+ for (suite_idx = IPA_UT_SUITE_FIRST_INDEX;
+ suite_idx < IPA_UT_SUITES_COUNT; suite_idx++) {
+ suite = IPA_UT_GET_SUITE(suite_idx);
+ ipa_assert_on(!suite);
+ if (!suite->tests) {
+ IPA_UT_DBG("No tests for suite %s\n",
+ suite->meta_data->name);
+ continue;
+ }
+ for (test_idx = 0; test_idx < suite->tests_cnt; test_idx++) {
+ suite->tests[test_idx].suite = suite;
+ IPA_UT_DBG("Updating test %s info for suite %s\n",
+ suite->tests[test_idx].name,
+ suite->meta_data->name);
+ }
+ }
+
+ ipa_ut_ctx->test_dbgfs_root = debugfs_create_dir("test",
+ ipa_ut_ctx->ipa_dbgfs_root);
+ if (!ipa_ut_ctx->test_dbgfs_root ||
+ IS_ERR(ipa_ut_ctx->test_dbgfs_root)) {
+ IPA_UT_ERR("failed to create test debugfs dir\n");
+ ret = -EFAULT;
+ goto unlock_mutex;
+ }
+
+ dfile_enable = debugfs_create_file("enable",
+ IPA_UT_READ_WRITE_DBG_FILE_MODE,
+ ipa_ut_ctx->test_dbgfs_root, 0, &ipa_ut_dbgfs_enable_fops);
+ if (!dfile_enable || IS_ERR(dfile_enable)) {
+ IPA_UT_ERR("failed to create enable debugfs file\n");
+ ret = -EFAULT;
+ goto fail_clean_dbgfs;
+ }
+
+ ipa_ut_ctx->inited = true;
+ IPA_UT_DBG("Done\n");
+ ret = 0;
+ goto unlock_mutex;
+
+fail_clean_dbgfs:
+ debugfs_remove_recursive(ipa_ut_ctx->test_dbgfs_root);
+unlock_mutex:
+ mutex_unlock(&ipa_ut_ctx->lock);
+ return ret;
+}
+
+/**
+ * ipa_ut_framework_destroy() - Destroy the UT framework info
+ *
+ * Disable it if enabled.
+ * Remove the debugfs entries using the root entry
+ */
+static void ipa_ut_framework_destroy(void)
+{
+ IPA_UT_DBG("Entry\n");
+
+ mutex_lock(&ipa_ut_ctx->lock);
+ if (ipa_ut_ctx->enabled)
+ ipa_ut_framework_disable();
+ if (ipa_ut_ctx->inited)
+ debugfs_remove_recursive(ipa_ut_ctx->test_dbgfs_root);
+ mutex_unlock(&ipa_ut_ctx->lock);
+}
+
+/**
+ * ipa_ut_ipa_ready_cb() - IPA ready CB
+ *
+ * Once IPA is ready starting initializing the unit-test framework
+ */
+static void ipa_ut_ipa_ready_cb(void *user_data)
+{
+ IPA_UT_DBG("Entry\n");
+ (void)ipa_ut_framework_init();
+}
+
+/**
+ * ipa_ut_module_init() - Module init
+ *
+ * Create the framework context, wait for IPA driver readiness
+ * and Initialize it.
+ * If IPA driver already ready, continue initialization immediately.
+ * if not, wait for IPA ready notification by IPA driver context
+ */
+static int __init ipa_ut_module_init(void)
+{
+ int ret;
+
+ IPA_UT_INFO("Loading IPA test module...\n");
+
+ ipa_ut_ctx = kzalloc(sizeof(struct ipa_ut_context), GFP_KERNEL);
+ if (!ipa_ut_ctx) {
+ IPA_UT_ERR("Failed to allocate ctx\n");
+ return -ENOMEM;
+ }
+ mutex_init(&ipa_ut_ctx->lock);
+
+ if (!ipa_is_ready()) {
+ IPA_UT_DBG("IPA driver not ready, registering callback\n");
+ ret = ipa_register_ipa_ready_cb(ipa_ut_ipa_ready_cb, NULL);
+
+ /*
+ * If we received -EEXIST, IPA has initialized. So we need
+ * to continue the initing process.
+ */
+ if (ret != -EEXIST) {
+ if (ret) {
+ IPA_UT_ERR("IPA CB reg failed - %d\n", ret);
+ kfree(ipa_ut_ctx);
+ ipa_ut_ctx = NULL;
+ }
+ return ret;
+ }
+ }
+
+ ret = ipa_ut_framework_init();
+ if (ret) {
+ IPA_UT_ERR("framework init failed\n");
+ kfree(ipa_ut_ctx);
+ ipa_ut_ctx = NULL;
+ }
+ return ret;
+}
+
+/**
+ * ipa_ut_module_exit() - Module exit function
+ *
+ * Destroys the Framework and removes its context
+ */
+static void ipa_ut_module_exit(void)
+{
+ IPA_UT_DBG("Entry\n");
+
+ if (!ipa_ut_ctx)
+ return;
+
+ ipa_ut_framework_destroy();
+ kfree(ipa_ut_ctx);
+ ipa_ut_ctx = NULL;
+}
+
+module_init(ipa_ut_module_init);
+module_exit(ipa_ut_module_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("IPA Unit Test module");
diff --git a/drivers/platform/msm/ipa/test/ipa_ut_framework.h b/drivers/platform/msm/ipa/test/ipa_ut_framework.h
new file mode 100644
index 000000000000..177be51bfe7d
--- /dev/null
+++ b/drivers/platform/msm/ipa/test/ipa_ut_framework.h
@@ -0,0 +1,222 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _IPA_UT_FRAMEWORK_H_
+#define _IPA_UT_FRAMEWORK_H_
+
+#include <linux/kernel.h>
+#include "../ipa_common_i.h"
+#include "ipa_ut_i.h"
+
+#define IPA_UT_DRV_NAME "ipa_ut"
+
+#define IPA_UT_DBG(fmt, args...) \
+ do { \
+ pr_debug(IPA_UT_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
+#define IPA_UT_DBG_LOW(fmt, args...) \
+ do { \
+ pr_debug(IPA_UT_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
+#define IPA_UT_ERR(fmt, args...) \
+ do { \
+ pr_err(IPA_UT_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
+#define IPA_UT_INFO(fmt, args...) \
+ do { \
+ pr_info(IPA_UT_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
+/**
+ * struct ipa_ut_tst_fail_report - Information on test failure
+ * @valid: When a test posts a report, valid will be marked true
+ * @file: File name containing the failed test.
+ * @line: Number of line in the file where the test failed.
+ * @func: Function where the test failed in.
+ * @info: Information about the failure.
+ */
+struct ipa_ut_tst_fail_report {
+ bool valid;
+ const char *file;
+ int line;
+ const char *func;
+ const char *info;
+};
+
+/**
+ * Report on test failure
+ * To be used by tests.
+ */
+#define IPA_UT_TEST_FAIL_REPORT(__info) \
+ do { \
+ extern struct ipa_ut_tst_fail_report \
+ _IPA_UT_TEST_FAIL_REPORT_DATA; \
+ _IPA_UT_TEST_FAIL_REPORT_DATA.valid = true; \
+ _IPA_UT_TEST_FAIL_REPORT_DATA.file = __FILENAME__; \
+ _IPA_UT_TEST_FAIL_REPORT_DATA.line = __LINE__; \
+ _IPA_UT_TEST_FAIL_REPORT_DATA.func = __func__; \
+ if (__info) \
+ _IPA_UT_TEST_FAIL_REPORT_DATA.info = __info; \
+ else \
+ _IPA_UT_TEST_FAIL_REPORT_DATA.info = ""; \
+ } while (0)
+
+/**
+ * To be used by tests to log progress and ongoing information
+ * Logs are not printed to user, but saved to a buffer.
+ * I/S shall print the buffer at different occasions - e.g. in test failure
+ */
+#define IPA_UT_LOG(fmt, args...) \
+ do { \
+ extern char *_IPA_UT_TEST_LOG_BUF_NAME; \
+ char __buf[512]; \
+ IPA_UT_DBG(fmt, args); \
+ scnprintf(__buf, sizeof(__buf), \
+ fmt, args); \
+ strlcat(_IPA_UT_TEST_LOG_BUF_NAME, __buf, sizeof(__buf)); \
+ } while (0)
+
+/**
+ * struct ipa_ut_suite_meta - Suite meta-data
+ * @name: Suite unique name
+ * @desc: Suite description
+ * @setup: Setup Call-back of the suite
+ * @teardown: Teardown Call-back of the suite
+ * @priv: Private pointer of the suite
+ *
+ * Setup/Teardown will be called once for the suite when running a tests of it.
+ * priv field is shared between the Setup/Teardown and the tests
+ */
+struct ipa_ut_suite_meta {
+ char *name;
+ char *desc;
+ int (*setup)(void **ppriv);
+ int (*teardown)(void *priv);
+ void *priv;
+};
+
+/* Test suite data structure declaration */
+struct ipa_ut_suite;
+
+/**
+ * struct ipa_ut_test - Test information
+ * @name: Test name
+ * @desc: Test description
+ * @run: Test execution call-back
+ * @run_in_regression: To run this test as part of regression?
+ * @min_ipa_hw_ver: Minimum IPA H/W version where the test is supported?
+ * @max_ipa_hw_ver: Maximum IPA H/W version where the test is supported?
+ * @suite: Pointer to suite containing this test
+ * @res: Test execution result. Will be updated after running a test as part
+ * of suite tests run
+ */
+struct ipa_ut_test {
+ char *name;
+ char *desc;
+ int (*run)(void *priv);
+ bool run_in_regression;
+ int min_ipa_hw_ver;
+ int max_ipa_hw_ver;
+ struct ipa_ut_suite *suite;
+ enum ipa_ut_test_result res;
+};
+
+/**
+ * struct ipa_ut_suite - Suite information
+ * @meta_data: Pointer to meta-data structure of the suite
+ * @tests: Pointer to array of tests belongs to the suite
+ * @tests_cnt: Number of tests
+ */
+struct ipa_ut_suite {
+ struct ipa_ut_suite_meta *meta_data;
+ struct ipa_ut_test *tests;
+ size_t tests_cnt;
+};
+
+
+/**
+ * Add a test to a suite.
+ * Will add entry to tests array and update its info with
+ * the given info, thus adding new test.
+ */
+#define IPA_UT_ADD_TEST(__name, __desc, __run, __run_in_regression, \
+ __min_ipa_hw_ver, __max_ipa__hw_ver) \
+ { \
+ .name = #__name, \
+ .desc = __desc, \
+ .run = __run, \
+ .run_in_regression = __run_in_regression, \
+ .min_ipa_hw_ver = __min_ipa_hw_ver, \
+ .max_ipa_hw_ver = __max_ipa__hw_ver, \
+ .suite = NULL, \
+ }
+
+/**
+ * Declare a suite
+ * Every suite need to be declared before it is registered.
+ */
+#define IPA_UT_DECLARE_SUITE(__name) \
+ extern struct ipa_ut_suite _IPA_UT_SUITE_DATA(__name)
+
+/**
+ * Register a suite
+ * Registering a suite is mandatory so it will be considered.
+ */
+#define IPA_UT_REGISTER_SUITE(__name) \
+ (&_IPA_UT_SUITE_DATA(__name))
+
+/**
+ * Start/End suite definition
+ * Will create the suite global structures and adds adding tests to it.
+ * Use IPA_UT_ADD_TEST() with these macros to add tests when defining
+ * a suite
+ */
+#define IPA_UT_DEFINE_SUITE_START(__name, __desc, __setup, __teardown) \
+ static struct ipa_ut_suite_meta _IPA_UT_SUITE_META_DATA(__name) = \
+ { \
+ .name = #__name, \
+ .desc = __desc, \
+ .setup = __setup, \
+ .teardown = __teardown, \
+ }; \
+ static struct ipa_ut_test _IPA_UT_SUITE_TESTS(__name)[] =
+#define IPA_UT_DEFINE_SUITE_END(__name) \
+ ; \
+ struct ipa_ut_suite _IPA_UT_SUITE_DATA(__name) = \
+ { \
+ .meta_data = &_IPA_UT_SUITE_META_DATA(__name), \
+ .tests = _IPA_UT_SUITE_TESTS(__name), \
+ .tests_cnt = ARRAY_SIZE(_IPA_UT_SUITE_TESTS(__name)), \
+ }
+
+#endif /* _IPA_UT_FRAMEWORK_H_ */
diff --git a/drivers/platform/msm/ipa/test/ipa_ut_i.h b/drivers/platform/msm/ipa/test/ipa_ut_i.h
new file mode 100644
index 000000000000..7cf5e53d0af1
--- /dev/null
+++ b/drivers/platform/msm/ipa/test/ipa_ut_i.h
@@ -0,0 +1,86 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _IPA_UT_I_H_
+#define _IPA_UT_I_H_
+
+/* Suite data global structure name */
+#define _IPA_UT_SUITE_DATA(__name) ipa_ut_ ##__name ##_data
+
+/* Suite meta-data global structure name */
+#define _IPA_UT_SUITE_META_DATA(__name) ipa_ut_ ##__name ##_meta_data
+
+/* Suite global array of tests */
+#define _IPA_UT_SUITE_TESTS(__name) ipa_ut_ ##__name ##_tests
+
+/* Global array of all suites */
+#define _IPA_UT_ALL_SUITES ipa_ut_all_suites_data
+
+/* Meta-test "all" name - test to run all tests in given suite */
+#define _IPA_UT_RUN_ALL_TEST_NAME "all"
+
+/**
+ * Meta-test "regression" name -
+ * test to run all regression tests in given suite
+ */
+#define _IPA_UT_RUN_REGRESSION_TEST_NAME "regression"
+
+
+/* Test Log buffer name and size */
+#define _IPA_UT_TEST_LOG_BUF_NAME ipa_ut_tst_log_buf
+#define _IPA_UT_TEST_LOG_BUF_SIZE 2048
+
+/* Global structure for test fail execution result information */
+#define _IPA_UT_TEST_FAIL_REPORT_DATA ipa_ut_tst_fail_report_data
+
+/* Start/End definitions of the array of suites */
+#define IPA_UT_DEFINE_ALL_SUITES_START \
+ static struct ipa_ut_suite *_IPA_UT_ALL_SUITES[] =
+#define IPA_UT_DEFINE_ALL_SUITES_END
+
+/**
+ * Suites iterator - Array-like container
+ * First index, number of elements and element fetcher
+ */
+#define IPA_UT_SUITE_FIRST_INDEX 0
+#define IPA_UT_SUITES_COUNT \
+ ARRAY_SIZE(_IPA_UT_ALL_SUITES)
+#define IPA_UT_GET_SUITE(__index) \
+ _IPA_UT_ALL_SUITES[__index]
+
+/**
+ * enum ipa_ut_test_result - Test execution result
+ * @IPA_UT_TEST_RES_FAIL: Test executed and failed
+ * @IPA_UT_TEST_RES_SUCCESS: Test executed and succeeded
+ * @IPA_UT_TEST_RES_SKIP: Test was not executed.
+ *
+ * When running all tests in a suite, a specific test could
+ * be skipped and not executed. For example due to mismatch of
+ * IPA H/W version.
+ */
+enum ipa_ut_test_result {
+ IPA_UT_TEST_RES_FAIL,
+ IPA_UT_TEST_RES_SUCCESS,
+ IPA_UT_TEST_RES_SKIP,
+};
+
+/**
+ * enum ipa_ut_meta_test_type - Type of suite meta-test
+ * @IPA_UT_META_TEST_ALL: Represents all tests in suite
+ * @IPA_UT_META_TEST_REGRESSION: Represents all regression tests in suite
+ */
+enum ipa_ut_meta_test_type {
+ IPA_UT_META_TEST_ALL,
+ IPA_UT_META_TEST_REGRESSION,
+};
+
+#endif /* _IPA_UT_I_H_ */
diff --git a/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h b/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h
new file mode 100644
index 000000000000..615ba671ebaa
--- /dev/null
+++ b/drivers/platform/msm/ipa/test/ipa_ut_suite_list.h
@@ -0,0 +1,35 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _IPA_UT_SUITE_LIST_H_
+#define _IPA_UT_SUITE_LIST_H_
+
+#include "ipa_ut_framework.h"
+#include "ipa_ut_i.h"
+
+/**
+ * Declare every suite here so that it will be found later below
+ * No importance for order.
+ */
+IPA_UT_DECLARE_SUITE(example);
+
+
+/**
+ * Register every suite inside the below block.
+ * Unregistered suites will be ignored
+ */
+IPA_UT_DEFINE_ALL_SUITES_START
+{
+ IPA_UT_REGISTER_SUITE(example),
+} IPA_UT_DEFINE_ALL_SUITES_END;
+
+#endif /* _IPA_UT_SUITE_LIST_H_ */
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index a45a5d103040..b1c3441b285a 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -225,9 +225,9 @@ static struct device_attribute power_supply_attrs[] = {
/* Local extensions */
POWER_SUPPLY_ATTR(usb_hc),
POWER_SUPPLY_ATTR(usb_otg),
- POWER_SUPPLY_ATTR(charge_enabled),
POWER_SUPPLY_ATTR(battery_charging_enabled),
POWER_SUPPLY_ATTR(charging_enabled),
+ POWER_SUPPLY_ATTR(pin_enabled),
POWER_SUPPLY_ATTR(input_suspend),
POWER_SUPPLY_ATTR(input_voltage_regulation),
POWER_SUPPLY_ATTR(input_current_max),
diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h
index cf7869ea1515..ef4ea8172035 100644
--- a/drivers/power/qcom-charger/fg-core.h
+++ b/drivers/power/qcom-charger/fg-core.h
@@ -40,7 +40,6 @@
#define SRAM_READ "fg_sram_read"
#define SRAM_WRITE "fg_sram_write"
-#define SRAM_UPDATE "fg_sram_update"
#define PROFILE_LOAD "fg_profile_load"
#define DELTA_SOC "fg_delta_soc"
diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c
index 2adc07ddc5a0..b350e53237b7 100644
--- a/drivers/power/qcom-charger/qpnp-fg-gen3.c
+++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c
@@ -413,13 +413,12 @@ static int fg_get_sram_prop(struct fg_chip *chip, enum fg_sram_param_id id,
if (id < 0 || id > FG_SRAM_MAX || chip->sp[id].len > sizeof(buf))
return -EINVAL;
- vote(chip->awake_votable, SRAM_UPDATE, true, 0);
rc = fg_sram_read(chip, chip->sp[id].address, chip->sp[id].offset,
buf, chip->sp[id].len, FG_IMA_DEFAULT);
if (rc < 0) {
pr_err("Error reading address 0x%04x[%d] rc=%d\n",
chip->sp[id].address, chip->sp[id].offset, rc);
- goto out;
+ return rc;
}
for (i = 0, temp = 0; i < chip->sp[id].len; i++)
@@ -427,9 +426,6 @@ static int fg_get_sram_prop(struct fg_chip *chip, enum fg_sram_param_id id,
*val = fg_decode(chip->sp, id, temp);
return 0;
-out:
- vote(chip->awake_votable, SRAM_UPDATE, false, 0);
- return rc;
}
#define BATT_TEMP_NUMR 1
diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c
index 8fe882e078f0..18b02fbde5a6 100644
--- a/drivers/power/qcom-charger/smb-lib.c
+++ b/drivers/power/qcom-charger/smb-lib.c
@@ -349,13 +349,20 @@ static int smblib_detach_usb(struct smb_charger *chg)
return rc;
}
-static int pl_notifier_call(struct notifier_block *nb,
+static int smblib_notifier_call(struct notifier_block *nb,
unsigned long ev, void *v)
{
struct power_supply *psy = v;
- struct smb_charger *chg = container_of(nb, struct smb_charger, pl.nb);
+ struct smb_charger *chg = container_of(nb, struct smb_charger, nb);
- if (strcmp(psy->desc->name, "parallel") == 0) {
+ if (!strcmp(psy->desc->name, "bms")) {
+ if (!chg->bms_psy)
+ chg->bms_psy = psy;
+ if (ev == PSY_EVENT_PROP_CHANGED && chg->batt_psy)
+ schedule_work(&chg->bms_update_work);
+ }
+
+ if (!chg->pl.psy && !strcmp(psy->desc->name, "parallel")) {
chg->pl.psy = psy;
schedule_work(&chg->pl_detect_work);
}
@@ -363,12 +370,12 @@ static int pl_notifier_call(struct notifier_block *nb,
return NOTIFY_OK;
}
-static int register_pl_notifier(struct smb_charger *chg)
+static int smblib_register_notifier(struct smb_charger *chg)
{
int rc;
- chg->pl.nb.notifier_call = pl_notifier_call;
- rc = power_supply_reg_notifier(&chg->pl.nb);
+ chg->nb.notifier_call = smblib_notifier_call;
+ rc = power_supply_reg_notifier(&chg->nb);
if (rc < 0) {
pr_err("Couldn't register psy notifier rc = %d\n", rc);
return rc;
@@ -740,8 +747,12 @@ int smblib_get_prop_batt_present(struct smb_charger *chg,
int smblib_get_prop_batt_capacity(struct smb_charger *chg,
union power_supply_propval *val)
{
- val->intval = 50;
- return 0;
+ int rc = -EINVAL;
+
+ if (chg->bms_psy)
+ rc = power_supply_get_property(chg->bms_psy,
+ POWER_SUPPLY_PROP_CAPACITY, val);
+ return rc;
}
int smblib_get_prop_batt_status(struct smb_charger *chg,
@@ -1677,9 +1688,12 @@ static void smblib_handle_typec_debounce_done(struct smb_charger *chg,
vote(chg->pl_disable_votable, TYPEC_SRC_VOTER,
!rising || sink_attached, 0);
- /* reset taper_end voter here */
- if (!rising || sink_attached)
+ if (!rising || sink_attached) {
+ /* icl votes to disable parallel charging */
+ vote(chg->pl_disable_votable, USBIN_ICL_VOTER, true, 0);
+ /* reset taper_end voter here */
vote(chg->pl_disable_votable, TAPER_END_VOTER, false, 0);
+ }
smblib_dbg(chg, PR_INTERRUPT, "IRQ: debounce-done %s; Type-C %s detected\n",
rising ? "rising" : "falling",
@@ -1735,13 +1749,18 @@ static void smblib_hvdcp_detect_work(struct work_struct *work)
}
}
+static void smblib_bms_update_work(struct work_struct *work)
+{
+ struct smb_charger *chg = container_of(work, struct smb_charger,
+ bms_update_work);
+ power_supply_changed(chg->batt_psy);
+}
+
static void smblib_pl_detect_work(struct work_struct *work)
{
struct smb_charger *chg = container_of(work, struct smb_charger,
pl_detect_work);
- power_supply_unreg_notifier(&chg->pl.nb);
-
if (!get_effective_result_locked(chg->pl_disable_votable))
rerun_election(chg->pl_disable_votable);
}
@@ -1884,6 +1903,7 @@ int smblib_init(struct smb_charger *chg)
int rc = 0;
mutex_init(&chg->write_lock);
+ INIT_WORK(&chg->bms_update_work, smblib_bms_update_work);
INIT_WORK(&chg->pl_detect_work, smblib_pl_detect_work);
INIT_DELAYED_WORK(&chg->hvdcp_detect_work, smblib_hvdcp_detect_work);
INIT_DELAYED_WORK(&chg->pl_taper_work, smblib_pl_taper_work);
@@ -1898,14 +1918,12 @@ int smblib_init(struct smb_charger *chg)
}
chg->pl.psy = power_supply_get_by_name("parallel");
- if (!chg->pl.psy) {
- rc = register_pl_notifier(chg);
- if (rc < 0) {
- dev_err(chg->dev,
- "Couldn't register notifier rc=%d\n",
- rc);
- return rc;
- }
+
+ rc = smblib_register_notifier(chg);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't register notifier rc=%d\n", rc);
+ return rc;
}
break;
@@ -1932,5 +1950,7 @@ int smblib_deinit(struct smb_charger *chg)
destroy_votable(chg->awake_votable);
destroy_votable(chg->pl_disable_votable);
+ power_supply_unreg_notifier(&chg->nb);
+
return 0;
}
diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h
index 1521fdb3fccf..47839074b724 100644
--- a/drivers/power/qcom-charger/smb-lib.h
+++ b/drivers/power/qcom-charger/smb-lib.h
@@ -74,7 +74,6 @@ struct smb_params {
};
struct parallel_params {
- struct notifier_block nb;
struct power_supply *psy;
int *master_percent;
int taper_percent;
@@ -96,8 +95,12 @@ struct smb_charger {
struct power_supply *batt_psy;
struct power_supply *usb_psy;
struct power_supply *dc_psy;
+ struct power_supply *bms_psy;
struct power_supply_desc usb_psy_desc;
+ /* notifiers */
+ struct notifier_block nb;
+
/* parallel charging */
struct parallel_params pl;
@@ -120,6 +123,7 @@ struct smb_charger {
struct votable *chg_disable_votable;
/* work */
+ struct work_struct bms_update_work;
struct work_struct pl_detect_work;
struct delayed_work hvdcp_detect_work;
struct delayed_work ps_change_timeout_work;
diff --git a/drivers/power/qcom-charger/smb138x-charger.c b/drivers/power/qcom-charger/smb138x-charger.c
index 11d936762e3c..e9006cfc0b9e 100644
--- a/drivers/power/qcom-charger/smb138x-charger.c
+++ b/drivers/power/qcom-charger/smb138x-charger.c
@@ -357,6 +357,8 @@ static int smb138x_init_batt_psy(struct smb138x *chip)
*****************************/
static enum power_supply_property smb138x_parallel_props[] = {
+ POWER_SUPPLY_PROP_CHARGING_ENABLED,
+ POWER_SUPPLY_PROP_PIN_ENABLED,
POWER_SUPPLY_PROP_INPUT_SUSPEND,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_CURRENT_MAX,
@@ -368,8 +370,21 @@ static int smb138x_parallel_get_prop(struct power_supply *psy,
{
struct smb_charger *chg = power_supply_get_drvdata(psy);
int rc = 0;
+ u8 temp;
switch (prop) {
+ case POWER_SUPPLY_PROP_CHARGING_ENABLED:
+ rc = smblib_read(chg, BATTERY_CHARGER_STATUS_5_REG,
+ &temp);
+ if (rc >= 0)
+ val->intval = (bool)(temp & CHARGING_ENABLE_BIT);
+ break;
+ case POWER_SUPPLY_PROP_PIN_ENABLED:
+ rc = smblib_read(chg, BATTERY_CHARGER_STATUS_5_REG,
+ &temp);
+ if (rc >= 0)
+ val->intval = !(temp & DISABLE_CHARGING_BIT);
+ break;
case POWER_SUPPLY_PROP_INPUT_SUSPEND:
rc = smblib_get_usb_suspend(chg, &val->intval);
break;
diff --git a/drivers/soc/qcom/core_hang_detect.c b/drivers/soc/qcom/core_hang_detect.c
index 42f31e320b61..e9b7f612dccc 100644
--- a/drivers/soc/qcom/core_hang_detect.c
+++ b/drivers/soc/qcom/core_hang_detect.c
@@ -33,6 +33,7 @@
#define _WRITE(x, y, z) (((~(_VAL(z))) & y) | _VALUE(x, z))
#define MODULE_NAME "msm_hang_detect"
+#define MAX_SYSFS_LEN 12
struct hang_detect {
phys_addr_t threshold[NR_CPUS];
@@ -108,8 +109,7 @@ static ssize_t show_threshold(struct kobject *kobj, struct attribute *attr,
{
struct hang_detect *device = to_core_hang_dev(kobj);
- return snprintf(buf, sizeof(device->threshold_val),
- "%u\n", device->threshold_val);
+ return snprintf(buf, MAX_SYSFS_LEN, "0x%x\n", device->threshold_val);
}
static size_t store_threshold(struct kobject *kobj, struct attribute *attr,
@@ -147,8 +147,8 @@ static ssize_t show_pmu_event_sel(struct kobject *kobj, struct attribute *attr,
{
struct hang_detect *hang_device = to_core_hang_dev(kobj);
- return snprintf(buf, sizeof(hang_device->pmu_event_sel),
- "%u\n", hang_device->pmu_event_sel);
+ return snprintf(buf, MAX_SYSFS_LEN, "0x%x\n",
+ hang_device->pmu_event_sel);
}
static size_t store_pmu_event_sel(struct kobject *kobj, struct attribute *attr,
@@ -188,8 +188,7 @@ static ssize_t show_enable(struct kobject *kobj, struct attribute *attr,
{
struct hang_detect *hang_device = to_core_hang_dev(kobj);
- return snprintf(buf, sizeof(hang_device->enabled),
- "%u\n", hang_device->enabled);
+ return snprintf(buf, MAX_SYSFS_LEN, "%u\n", hang_device->enabled);
}
static size_t store_enable(struct kobject *kobj, struct attribute *attr,
diff --git a/drivers/soc/qcom/gladiator_hang_detect.c b/drivers/soc/qcom/gladiator_hang_detect.c
index fd8062ca523a..e2bbe26decc8 100644
--- a/drivers/soc/qcom/gladiator_hang_detect.c
+++ b/drivers/soc/qcom/gladiator_hang_detect.c
@@ -34,6 +34,7 @@
#define NR_GLA_REG 6
#define MODULE_NAME "gladiator_hang_detect"
#define MAX_THRES 0xFFFFFFFF
+#define MAX_LEN_SYSFS 12
struct hang_detect {
phys_addr_t threshold[NR_GLA_REG];
@@ -199,8 +200,7 @@ static inline ssize_t generic_enable_show(struct kobject *kobj,
uint32_t reg_value;
get_enable(offset, hang_dev, &reg_value);
- return snprintf(buf, sizeof(hang_dev->ACE_enable),
- "%d\n", reg_value);
+ return snprintf(buf, MAX_LEN_SYSFS, "%u\n", reg_value);
}
static inline ssize_t generic_threshold_show(struct kobject *kobj,
@@ -210,9 +210,7 @@ static inline ssize_t generic_threshold_show(struct kobject *kobj,
uint32_t reg_value;
get_threshold(offset, hang_dev, &reg_value);
- return snprintf(buf, sizeof(hang_dev->ACE_threshold),
- "%u\n", reg_value);
-
+ return snprintf(buf, MAX_LEN_SYSFS, "0x%x\n", reg_value);
}
static inline size_t generic_threshold_store(struct kobject *kobj,
diff --git a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
index 7e5f1661932f..dfd6b448a65f 100644
--- a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
+++ b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
@@ -316,14 +316,7 @@ struct apr_svc_ch_dev *apr_tal_open(uint32_t clnt, uint32_t dest, uint32_t dl,
open_cfg.notify_rx_intent_req = apr_tal_notify_rx_intent_req;
open_cfg.notify_remote_rx_intent = apr_tal_notify_remote_rx_intent;
open_cfg.priv = apr_ch;
- /*
- * The transport name "smd_trans" is required if far end is using SMD.
- * In that case Glink will fall back to SMD and the client (APR in this
- * case) will still work as if Glink is the communication channel.
- * If far end is already using Glink, this property will be ignored in
- * Glink layer and communication will be through Glink.
- */
- open_cfg.transport = "smd_trans";
+ open_cfg.transport = "smem";
apr_ch->channel_state = GLINK_REMOTE_DISCONNECTED;
apr_ch->handle = glink_open(&open_cfg);
@@ -420,13 +413,13 @@ static void apr_tal_link_state_cb(struct glink_link_state_cb_info *cb_info,
}
static struct glink_link_info mpss_link_info = {
- .transport = NULL,
+ .transport = "smem",
.edge = "mpss",
.glink_link_state_notif_cb = apr_tal_link_state_cb,
};
static struct glink_link_info lpass_link_info = {
- .transport = NULL,
+ .transport = "smem",
.edge = "lpass",
.glink_link_state_notif_cb = apr_tal_link_state_cb,
};
diff --git a/drivers/soc/qcom/qsee_ipc_irq_bridge.c b/drivers/soc/qcom/qsee_ipc_irq_bridge.c
index d3a2212f07c4..ab43bbb7e86a 100644
--- a/drivers/soc/qcom/qsee_ipc_irq_bridge.c
+++ b/drivers/soc/qcom/qsee_ipc_irq_bridge.c
@@ -374,6 +374,9 @@ static int qiib_parse_node(struct device_node *node, struct qiib_dev *devp)
}
QIIB_DBG("%s: %s = %d\n", __func__, key, devp->irq_line);
+ irqtype = irqd_get_trigger_type(irq_get_irq_data(devp->irq_line));
+ QIIB_DBG("%s: irqtype = %d\n", __func__, irqtype);
+
key = "label";
subsys_name = of_get_property(node, key, NULL);
if (!subsys_name) {
@@ -382,8 +385,8 @@ static int qiib_parse_node(struct device_node *node, struct qiib_dev *devp)
}
QIIB_DBG("%s: %s = %s\n", __func__, key, subsys_name);
- if ((irqtype & IRQF_TRIGGER_HIGH) && !strcmp(devp->ssr_name, "mpss")) {
- key = "qcom,irq-mask";
+ if (irqtype & IRQF_TRIGGER_HIGH) {
+ key = "qcom,rx-irq-clr-mask";
ret = of_property_read_u32(node, key, &devp->irq_mask);
if (ret) {
QIIB_ERR("%s: missing key: %s\n", __func__, key);
@@ -422,9 +425,6 @@ static int qiib_parse_node(struct device_node *node, struct qiib_dev *devp)
goto ssr_reg_fail;
}
- irqtype = irqd_get_trigger_type(irq_get_irq_data(devp->irq_line));
- QIIB_DBG("%s: irqtype = %d\n", __func__, irqtype);
-
ret = request_irq(devp->irq_line, qiib_irq_handler,
irqtype | IRQF_NO_SUSPEND,
devp->dev_name, devp);
diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c
index 2bc425a437b2..9426e0751c4a 100644
--- a/drivers/soc/qcom/service-locator.c
+++ b/drivers/soc/qcom/service-locator.c
@@ -124,7 +124,7 @@ static void service_locator_svc_arrive(struct work_struct *work)
qmi_handle_destroy(service_locator.clnt_handle);
service_locator.clnt_handle = NULL;
mutex_unlock(&service_locator.service_mutex);
- pr_err("Unable to connnect to service\n");
+ pr_err("Unable to connnect to service rc:%d\n", rc);
return;
}
if (!service_inited)
@@ -148,10 +148,12 @@ static void service_locator_recv_msg(struct work_struct *work)
do {
pr_debug("Notified about a Receive event\n");
- } while ((ret = qmi_recv_msg(service_locator.clnt_handle)) == 0);
+ ret = qmi_recv_msg(service_locator.clnt_handle);
+ if (ret != -ENOMSG)
+ pr_err("Error receiving message rc:%d. Retrying...\n",
+ ret);
+ } while (ret == 0);
- if (ret != -ENOMSG)
- pr_err("Error receiving message\n");
}
static void store_get_domain_list_response(struct pd_qmi_client_data *pd,
@@ -255,7 +257,7 @@ static int service_locator_send_msg(struct pd_qmi_client_data *pd)
rc = servreg_loc_send_msg(&req_desc, &resp_desc, req, resp,
pd);
if (rc < 0) {
- pr_err("send msg failed! 0x%x\n", rc);
+ pr_err("send msg failed rc:%d\n", rc);
goto out;
}
if (!domains_read) {
@@ -325,7 +327,7 @@ static int init_service_locator(void)
SERVREG_LOC_SERVICE_VERS_V01, SERVREG_LOC_SERVICE_INSTANCE_ID,
&service_locator.notifier);
if (rc < 0) {
- pr_err("Notifier register failed!\n");
+ pr_err("Notifier register failed rc:%d\n", rc);
goto inited;
}
@@ -397,8 +399,8 @@ static void pd_locator_work(struct work_struct *work)
}
rc = service_locator_send_msg(data);
if (rc) {
- pr_err("Failed to get process domains for %s for client %s\n",
- data->service_name, data->client_name);
+ pr_err("Failed to get process domains for %s for client %s rc:%d\n",
+ data->service_name, data->client_name, rc);
pdqw->notifier->notifier_call(pdqw->notifier,
LOCATOR_DOWN, NULL);
goto err;
diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c
index 1ada600495df..81dde8ca1ae8 100644
--- a/drivers/soc/qcom/service-notifier.c
+++ b/drivers/soc/qcom/service-notifier.c
@@ -140,21 +140,11 @@ static int service_notif_queue_notification(struct service_notif_info
enum qmi_servreg_notif_service_state_enum_type_v01 notif_type,
void *info)
{
- int ret = 0;
-
- if (!service_notif)
- return -EINVAL;
-
- if ((int) notif_type < QMI_STATE_MIN_VAL ||
- (int) notif_type > QMI_STATE_MAX_VAL)
- return -EINVAL;
+ int ret;
if (service_notif->curr_state == notif_type)
return 0;
- if (!service_notif->service_notif_rcvr_list.head)
- return 0;
-
ret = srcu_notifier_call_chain(&service_notif->service_notif_rcvr_list,
notif_type, info);
return ret;
@@ -244,8 +234,8 @@ static void root_service_service_ind_cb(struct qmi_handle *handle,
ind_desc.ei_array = qmi_servreg_notif_state_updated_ind_msg_v01_ei;
rc = qmi_kernel_decode(&ind_desc, &ind_msg, msg, msg_len);
if (rc < 0) {
- pr_err("Failed to decode message!\n");
- goto send_ind_resp;
+ pr_err("Failed to decode message rc:%d\n", rc);
+ return;
}
pr_debug("Indication received from %s, state: 0x%x, trans-id: %d\n",
@@ -263,15 +253,15 @@ static void root_service_service_ind_cb(struct qmi_handle *handle,
else {
mutex_lock(&notif_add_lock);
mutex_lock(&service_list_lock);
- if (service_notif_queue_notification(service_notif,
- ind_msg.curr_state, NULL))
- pr_err("Nnotification failed for %s\n",
- ind_msg.service_name);
+ rc = service_notif_queue_notification(service_notif,
+ ind_msg.curr_state, NULL);
+ if (rc & NOTIFY_STOP_MASK)
+ pr_err("Notifier callback aborted for %s with error %d\n",
+ ind_msg.service_name, rc);
service_notif->curr_state = ind_msg.curr_state;
mutex_unlock(&service_list_lock);
mutex_unlock(&notif_add_lock);
}
-send_ind_resp:
data->ind_msg.transaction_id = ind_msg.transaction_id;
snprintf(data->ind_msg.service_path,
ARRAY_SIZE(data->ind_msg.service_path), "%s",
@@ -320,7 +310,8 @@ static int send_notif_listener_msg_req(struct service_notif_info *service_notif,
if ((int) resp.curr_state < QMI_STATE_MIN_VAL ||
(int) resp.curr_state > QMI_STATE_MAX_VAL) {
- pr_err("Invalid notif info 0x%x\n", resp.curr_state);
+ pr_err("Invalid indication notification state %d\n",
+ resp.curr_state);
rc = -EINVAL;
}
*curr_state = resp.curr_state;
@@ -356,8 +347,8 @@ static void root_service_service_arrive(struct work_struct *work)
SERVREG_NOTIF_SERVICE_ID, SERVREG_NOTIF_SERVICE_VERS,
data->instance_id);
if (rc < 0) {
- pr_err("Could not connect handle to service(instance-id: %d)\n",
- data->instance_id);
+ pr_err("Could not connect to service(instance-id: %d) rc:%d\n",
+ data->instance_id, rc);
qmi_handle_destroy(data->clnt_handle);
data->clnt_handle = NULL;
return;
@@ -369,8 +360,8 @@ static void root_service_service_arrive(struct work_struct *work)
rc = qmi_register_ind_cb(data->clnt_handle, root_service_service_ind_cb,
(void *)data);
if (rc < 0)
- pr_err("Indication callback register failed(instance-id: %d)\n",
- data->instance_id);
+ pr_err("Indication callback register failed(instance-id: %d) rc:%d\n",
+ data->instance_id, rc);
mutex_lock(&notif_add_lock);
mutex_lock(&service_list_lock);
@@ -379,15 +370,14 @@ static void root_service_service_arrive(struct work_struct *work)
rc = register_notif_listener(service_notif, data,
&curr_state);
if (rc) {
- pr_err("Notifier registration failed for %s\n",
- service_notif->service_path);
+ pr_err("Notifier registration failed for %s rc:%d\n",
+ service_notif->service_path, rc);
} else {
rc = service_notif_queue_notification(
- service_notif,
- curr_state, NULL);
- if (rc)
- pr_err("Notifier failed for %s\n",
- service_notif->service_path);
+ service_notif, curr_state, NULL);
+ if (rc & NOTIFY_STOP_MASK)
+ pr_err("Notifier callback aborted for %s error:%d\n",
+ service_notif->service_path, rc);
service_notif->curr_state = curr_state;
}
}
@@ -412,9 +402,9 @@ static void root_service_service_exit(struct qmi_client_info *data)
rc = service_notif_queue_notification(service_notif,
SERVREG_NOTIF_SERVICE_STATE_DOWN_V01,
NULL);
- if (rc)
- pr_err("Notification failed for %s\n",
- service_notif->service_path);
+ if (rc & NOTIFY_STOP_MASK)
+ pr_err("Notifier callback aborted for %s with error %d\n",
+ service_notif->service_path, rc);
service_notif->curr_state =
SERVREG_NOTIF_SERVICE_STATE_DOWN_V01;
}
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 95191221bc3c..2c26ae1e3eb7 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1005,7 +1005,6 @@ struct dwc3 {
/* IRQ timing statistics */
int irq;
- struct tasklet_struct bh;
unsigned long irq_cnt;
unsigned bh_completion_time[MAX_INTR_STATS];
unsigned bh_handled_evt_cnt[MAX_INTR_STATS];
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 4d35de1c14c5..37a3c954a1dd 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -187,6 +187,7 @@ struct dwc3_msm {
u32 bus_perf_client;
struct msm_bus_scale_pdata *bus_scale_table;
struct power_supply *usb_psy;
+ struct work_struct vbus_draw_work;
bool in_host_mode;
unsigned int tx_fifo_size;
bool vbus_active;
@@ -1595,6 +1596,15 @@ static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *mdwc)
}
+static void dwc3_msm_vbus_draw_work(struct work_struct *w)
+{
+ struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm,
+ vbus_draw_work);
+ struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
+
+ dwc3_msm_gadget_vbus_draw(mdwc, dwc->vbus_draw);
+}
+
static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event)
{
struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
@@ -1680,7 +1690,7 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event)
break;
case DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT:
dev_dbg(mdwc->dev, "DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT received\n");
- dwc3_msm_gadget_vbus_draw(mdwc, dwc->vbus_draw);
+ schedule_work(&mdwc->vbus_draw_work);
break;
case DWC3_CONTROLLER_RESTART_USB_SESSION:
dev_dbg(mdwc->dev, "DWC3_CONTROLLER_RESTART_USB_SESSION received\n");
@@ -1927,6 +1937,12 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
clk_disable_unprepare(mdwc->bus_aggr_clk);
clk_disable_unprepare(mdwc->utmi_clk);
+ /* Memory core: OFF, Memory periphery: OFF */
+ if (!mdwc->in_host_mode && !mdwc->vbus_active) {
+ clk_set_flags(mdwc->core_clk, CLKFLAG_NORETAIN_MEM);
+ clk_set_flags(mdwc->core_clk, CLKFLAG_NORETAIN_PERIPH);
+ }
+
clk_set_rate(mdwc->core_clk, 19200000);
clk_disable_unprepare(mdwc->core_clk);
/*
@@ -2338,14 +2354,23 @@ static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc)
return ret;
}
- /*
- * Get Max supported clk frequency for USB Core CLK and request
- * to set the same.
- */
- mdwc->core_clk_rate = clk_round_rate(mdwc->core_clk, LONG_MAX);
+ if (!of_property_read_u32(mdwc->dev->of_node, "qcom,core-clk-rate",
+ (u32 *)&mdwc->core_clk_rate)) {
+ mdwc->core_clk_rate = clk_round_rate(mdwc->core_clk,
+ mdwc->core_clk_rate);
+ } else {
+ /*
+ * Get Max supported clk frequency for USB Core CLK and request
+ * to set the same.
+ */
+ mdwc->core_clk_rate = clk_round_rate(mdwc->core_clk, LONG_MAX);
+ }
+
if (IS_ERR_VALUE(mdwc->core_clk_rate)) {
dev_err(mdwc->dev, "fail to get core clk max freq.\n");
} else {
+ dev_dbg(mdwc->dev, "USB core frequency = %ld\n",
+ mdwc->core_clk_rate);
ret = clk_set_rate(mdwc->core_clk, mdwc->core_clk_rate);
if (ret)
dev_err(mdwc->dev, "fail to set core_clk freq:%d\n",
@@ -2582,6 +2607,7 @@ static int dwc3_msm_probe(struct platform_device *pdev)
INIT_WORK(&mdwc->resume_work, dwc3_resume_work);
INIT_WORK(&mdwc->restart_usb_work, dwc3_restart_usb_work);
INIT_WORK(&mdwc->bus_vote_w, dwc3_msm_bus_vote_w);
+ INIT_WORK(&mdwc->vbus_draw_work, dwc3_msm_vbus_draw_work);
INIT_DELAYED_WORK(&mdwc->sm_work, dwc3_otg_sm_work);
mdwc->dwc3_wq = alloc_ordered_workqueue("dwc3_wq", 0);
@@ -3165,7 +3191,8 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on)
static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA)
{
- union power_supply_propval pval = {0,};
+ union power_supply_propval pval = {1000 * mA};
+ int ret;
if (mdwc->charging_disabled)
return 0;
@@ -3183,42 +3210,16 @@ static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA)
dev_info(mdwc->dev, "Avail curr from USB = %u\n", mA);
- if (mdwc->max_power <= 2 && mA > 2) {
- /* Enable Charging */
- pval.intval = true;
- if (power_supply_set_property(mdwc->usb_psy,
- POWER_SUPPLY_PROP_ONLINE, &pval))
- goto psy_error;
- pval.intval = 1000 * mA;
- if (power_supply_set_property(mdwc->usb_psy,
- POWER_SUPPLY_PROP_CURRENT_MAX, &pval))
- goto psy_error;
- } else if (mdwc->max_power > 0 && (mA == 0 || mA == 2)) {
- /* Disable charging */
- pval.intval = false;
- if (power_supply_set_property(mdwc->usb_psy,
- POWER_SUPPLY_PROP_ONLINE, &pval))
- goto psy_error;
- } else {
- /* Enable charging */
- pval.intval = true;
- if (power_supply_set_property(mdwc->usb_psy,
- POWER_SUPPLY_PROP_ONLINE, &pval))
- goto psy_error;
- }
-
/* Set max current limit in uA */
- pval.intval = 1000 * mA;
- if (power_supply_set_property(mdwc->usb_psy,
- POWER_SUPPLY_PROP_CURRENT_MAX, &pval))
- goto psy_error;
+ ret = power_supply_set_property(mdwc->usb_psy,
+ POWER_SUPPLY_PROP_CURRENT_MAX, &pval);
+ if (ret) {
+ dev_dbg(mdwc->dev, "power supply error when setting property\n");
+ return ret;
+ }
mdwc->max_power = mA;
return 0;
-
-psy_error:
- dev_dbg(mdwc->dev, "power supply error when setting property\n");
- return -ENXIO;
}
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 7d97aeb21340..acaa99615d33 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2141,8 +2141,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
atomic_read(&dwc->dev->power.usage_count));
dwc3_gadget_disable_irq(dwc);
- tasklet_kill(&dwc->bh);
-
spin_lock_irqsave(&dwc->lock, flags);
__dwc3_gadget_ep_disable(dwc->eps[0]);
@@ -3380,15 +3378,6 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
return ret;
}
-static void dwc3_interrupt_bh(unsigned long param)
-{
- struct dwc3 *dwc = (struct dwc3 *) param;
-
- pm_runtime_get(dwc->dev);
- dwc3_thread_interrupt(dwc->irq, dwc);
- enable_irq(dwc->irq);
-}
-
static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
{
struct dwc3 *dwc = _dwc;
@@ -3412,7 +3401,6 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
dwc->bh_completion_time[dwc->bh_dbg_index] = temp_time;
dwc->bh_dbg_index = (dwc->bh_dbg_index + 1) % 10;
- pm_runtime_put(dwc->dev);
return ret;
}
@@ -3478,10 +3466,8 @@ irqreturn_t dwc3_interrupt(int irq, void *_dwc)
dwc->irq_event_count[dwc->irq_dbg_index] = temp_cnt / 4;
dwc->irq_dbg_index = (dwc->irq_dbg_index + 1) % MAX_INTR_STATS;
- if (ret == IRQ_WAKE_THREAD) {
- disable_irq_nosync(irq);
- tasklet_schedule(&dwc->bh);
- }
+ if (ret == IRQ_WAKE_THREAD)
+ dwc3_thread_interrupt(dwc->irq, dwc);
return IRQ_HANDLED;
}
@@ -3529,9 +3515,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
goto err3;
}
- dwc->bh.func = dwc3_interrupt_bh;
- dwc->bh.data = (unsigned long)dwc;
-
dwc->gadget.ops = &dwc3_gadget_ops;
dwc->gadget.speed = USB_SPEED_UNKNOWN;
dwc->gadget.sg_supported = true;
diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c
index b22ea656367e..78c1ce793b5b 100644
--- a/drivers/usb/gadget/function/f_cdev.c
+++ b/drivers/usb/gadget/function/f_cdev.c
@@ -516,7 +516,6 @@ static void usb_cser_disable(struct usb_function *f)
usb_cser_disconnect(port);
usb_ep_disable(port->port_usb.notify);
- usb_cser_free_req(port->port_usb.notify, port->port_usb.notify_req);
port->port_usb.notify->driver_data = NULL;
}
@@ -817,7 +816,11 @@ static void cser_free_inst(struct usb_function_instance *fi)
static void usb_cser_unbind(struct usb_configuration *c, struct usb_function *f)
{
+ struct f_cdev *port = func_to_port(f);
+
usb_free_all_descriptors(f);
+ usb_cser_free_req(port->port_usb.notify, port->port_usb.notify_req);
+ port->port_usb.notify_req = NULL;
}
static int usb_cser_alloc_requests(struct usb_ep *ep, struct list_head *head,
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index f29c275c490b..7bc6b5340dd7 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -849,10 +849,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
POWER_SUPPLY_PROP_VOLTAGE_MAX, &val);
pd->current_voltage = pd->requested_voltage;
- val.intval = pd->requested_current * 1000; /* mA->uA */
- power_supply_set_property(pd->usb_psy,
- POWER_SUPPLY_PROP_CURRENT_MAX, &val);
-
/* recursive call; go back to beginning state */
usbpd_set_state(pd, PE_SNK_STARTUP);
break;
@@ -1615,7 +1611,12 @@ static void usbpd_sm(struct work_struct *w)
POWER_SUPPLY_PROP_PD_ACTIVE, &val);
pd->requested_voltage = 5000000;
- pd->requested_current = max_sink_current;
+
+ if (pd->requested_current) {
+ val.intval = pd->requested_current = 0;
+ power_supply_set_property(pd->usb_psy,
+ POWER_SUPPLY_PROP_CURRENT_MAX, &val);
+ }
val.intval = pd->requested_voltage;
power_supply_set_property(pd->usb_psy,
diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h
index b601cafba6fd..61e99f47f02f 100644
--- a/drivers/video/fbdev/msm/mdss.h
+++ b/drivers/video/fbdev/msm/mdss.h
@@ -460,6 +460,7 @@ struct mdss_data_type {
struct ion_client *iclient;
int iommu_attached;
+ u32 dbg_bus_flags;
struct debug_bus *dbg_bus;
u32 dbg_bus_size;
struct vbif_debug_bus *vbif_dbg_bus;
diff --git a/drivers/video/fbdev/msm/mdss_debug.h b/drivers/video/fbdev/msm/mdss_debug.h
index 35ae81e4709e..59ba4f3e5578 100644
--- a/drivers/video/fbdev/msm/mdss_debug.h
+++ b/drivers/video/fbdev/msm/mdss_debug.h
@@ -31,6 +31,8 @@
#define XLOG_FUNC_EXIT 0x2222
#define MDSS_REG_BLOCK_NAME_LEN (5)
+#define DEBUG_FLAGS_DSPP BIT(0)
+
enum mdss_dbg_reg_dump_flag {
MDSS_DBG_DUMP_IN_LOG = BIT(0),
MDSS_DBG_DUMP_IN_MEM = BIT(1),
diff --git a/drivers/video/fbdev/msm/mdss_debug_xlog.c b/drivers/video/fbdev/msm/mdss_debug_xlog.c
index a34bce1200d8..32bfb151eddd 100644
--- a/drivers/video/fbdev/msm/mdss_debug_xlog.c
+++ b/drivers/video/fbdev/msm/mdss_debug_xlog.c
@@ -234,6 +234,7 @@ static void mdss_dump_debug_bus(u32 bus_dump_flag,
phys_addr_t phys = 0;
int list_size = mdata->dbg_bus_size;
int i;
+ u32 offset;
if (!(mdata->dbg_bus && list_size))
return;
@@ -267,8 +268,14 @@ static void mdss_dump_debug_bus(u32 bus_dump_flag,
writel_relaxed(TEST_MASK(head->block_id, head->test_id),
mdss_res->mdp_base + head->wr_addr);
wmb(); /* make sure test bits were written */
+
+ if (mdata->dbg_bus_flags & DEBUG_FLAGS_DSPP)
+ offset = MDSS_MDP_DSPP_DEBUGBUS_STATUS;
+ else
+ offset = head->wr_addr + 0x4;
+
status = readl_relaxed(mdss_res->mdp_base +
- head->wr_addr + 0x4);
+ offset);
if (in_log)
pr_err("waddr=0x%x blk=%d tst=%d val=0x%x\n",
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index 3785a701e3c1..78dc17536416 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -459,6 +459,9 @@ void mdss_dsi_host_init(struct mdss_panel_data *pdata)
/* enable contention detection for receiving */
mdss_dsi_lp_cd_rx(ctrl_pdata);
+ /* set DMA FIFO read watermark to 15/16 full */
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x50, 0x30);
+
wmb();
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index da60570c7085..921391dc4bde 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -56,7 +56,8 @@
#define C0_G_Y 0 /* G/luma */
/* wait for at most 2 vsync for lowest refresh rate (24hz) */
-#define KOFF_TIMEOUT msecs_to_jiffies(84)
+#define KOFF_TIMEOUT_MS 84
+#define KOFF_TIMEOUT msecs_to_jiffies(KOFF_TIMEOUT_MS)
#define OVERFETCH_DISABLE_TOP BIT(0)
#define OVERFETCH_DISABLE_BOTTOM BIT(1)
diff --git a/drivers/video/fbdev/msm/mdss_mdp_debug.c b/drivers/video/fbdev/msm/mdss_mdp_debug.c
index f19161ad25c4..9e3c2b7cdd1b 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_debug.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_debug.c
@@ -937,6 +937,785 @@ static struct debug_bus dbg_bus_8996[] = {
{ 0x418, 60, 0},
};
+
+static struct debug_bus dbg_bus_msmcobalt[] = {
+
+ /*
+ * sspp0 - 0x188
+ * sspp1 - 0x298
+ * dspp - 0x348
+ * periph - 0x418
+ */
+
+ /* Unpack 0 sspp 0*/
+ { 0x188, 50, 2 },
+ { 0x188, 60, 2 },
+ { 0x188, 70, 2 },
+ { 0x188, 85, 2 },
+ /* Upack 0 sspp 1*/
+ { 0x298, 50, 2 },
+ { 0x298, 60, 2 },
+ { 0x298, 70, 2 },
+ { 0x298, 85, 2 },
+ /* scheduler */
+ { 0x348, 130, 0 },
+ { 0x348, 130, 1 },
+ { 0x348, 130, 2 },
+ { 0x348, 130, 3 },
+ { 0x348, 130, 4 },
+ { 0x348, 130, 5 },
+
+ /* qseed */
+ {0x188, 6, 0},
+ {0x188, 6, 1},
+ {0x188, 26, 0},
+ {0x188, 26, 1},
+ {0x298, 6, 0},
+ {0x298, 6, 1},
+ {0x298, 26, 0},
+ {0x298, 26, 1},
+
+ /* scale */
+ {0x188, 16, 0},
+ {0x188, 16, 1},
+ {0x188, 36, 0},
+ {0x188, 36, 1},
+ {0x298, 16, 0},
+ {0x298, 16, 1},
+ {0x298, 36, 0},
+ {0x298, 36, 1},
+
+ /* fetch sspp0 */
+
+ /* vig 0 */
+ { 0x188, 0, 0 },
+ { 0x188, 0, 1 },
+ { 0x188, 0, 2 },
+ { 0x188, 0, 3 },
+ { 0x188, 0, 4 },
+ { 0x188, 0, 5 },
+ { 0x188, 0, 6 },
+ { 0x188, 0, 7 },
+
+ { 0x188, 1, 0 },
+ { 0x188, 1, 1 },
+ { 0x188, 1, 2 },
+ { 0x188, 1, 3 },
+ { 0x188, 1, 4 },
+ { 0x188, 1, 5 },
+ { 0x188, 1, 6 },
+ { 0x188, 1, 7 },
+
+ { 0x188, 2, 0 },
+ { 0x188, 2, 1 },
+ { 0x188, 2, 2 },
+ { 0x188, 2, 3 },
+ { 0x188, 2, 4 },
+ { 0x188, 2, 5 },
+ { 0x188, 2, 6 },
+ { 0x188, 2, 7 },
+
+ { 0x188, 4, 0 },
+ { 0x188, 4, 1 },
+ { 0x188, 4, 2 },
+ { 0x188, 4, 3 },
+ { 0x188, 4, 4 },
+ { 0x188, 4, 5 },
+ { 0x188, 4, 6 },
+ { 0x188, 4, 7 },
+
+ { 0x188, 5, 0 },
+ { 0x188, 5, 1 },
+ { 0x188, 5, 2 },
+ { 0x188, 5, 3 },
+ { 0x188, 5, 4 },
+ { 0x188, 5, 5 },
+ { 0x188, 5, 6 },
+ { 0x188, 5, 7 },
+
+ /* vig 2 */
+ { 0x188, 20, 0 },
+ { 0x188, 20, 1 },
+ { 0x188, 20, 2 },
+ { 0x188, 20, 3 },
+ { 0x188, 20, 4 },
+ { 0x188, 20, 5 },
+ { 0x188, 20, 6 },
+ { 0x188, 20, 7 },
+
+ { 0x188, 21, 0 },
+ { 0x188, 21, 1 },
+ { 0x188, 21, 2 },
+ { 0x188, 21, 3 },
+ { 0x188, 21, 4 },
+ { 0x188, 21, 5 },
+ { 0x188, 21, 6 },
+ { 0x188, 21, 7 },
+
+ { 0x188, 22, 0 },
+ { 0x188, 22, 1 },
+ { 0x188, 22, 2 },
+ { 0x188, 22, 3 },
+ { 0x188, 22, 4 },
+ { 0x188, 22, 5 },
+ { 0x188, 22, 6 },
+ { 0x188, 22, 7 },
+
+ { 0x188, 24, 0 },
+ { 0x188, 24, 1 },
+ { 0x188, 24, 2 },
+ { 0x188, 24, 3 },
+ { 0x188, 24, 4 },
+ { 0x188, 24, 5 },
+ { 0x188, 24, 6 },
+ { 0x188, 24, 7 },
+
+ { 0x188, 25, 0 },
+ { 0x188, 25, 1 },
+ { 0x188, 25, 2 },
+ { 0x188, 25, 3 },
+ { 0x188, 25, 4 },
+ { 0x188, 25, 5 },
+ { 0x188, 25, 6 },
+ { 0x188, 25, 7 },
+
+ /* dma 2 */
+ { 0x188, 30, 0 },
+ { 0x188, 30, 1 },
+ { 0x188, 30, 2 },
+ { 0x188, 30, 3 },
+ { 0x188, 30, 4 },
+ { 0x188, 30, 5 },
+ { 0x188, 30, 6 },
+ { 0x188, 30, 7 },
+
+ { 0x188, 31, 0 },
+ { 0x188, 31, 1 },
+ { 0x188, 31, 2 },
+ { 0x188, 31, 3 },
+ { 0x188, 31, 4 },
+ { 0x188, 31, 5 },
+ { 0x188, 31, 6 },
+ { 0x188, 31, 7 },
+
+ { 0x188, 32, 0 },
+ { 0x188, 32, 1 },
+ { 0x188, 32, 2 },
+ { 0x188, 32, 3 },
+ { 0x188, 32, 4 },
+ { 0x188, 32, 5 },
+ { 0x188, 32, 6 },
+ { 0x188, 32, 7 },
+
+ { 0x188, 33, 0 },
+ { 0x188, 33, 1 },
+ { 0x188, 33, 2 },
+ { 0x188, 33, 3 },
+ { 0x188, 33, 4 },
+ { 0x188, 33, 5 },
+ { 0x188, 33, 6 },
+ { 0x188, 33, 7 },
+
+ { 0x188, 34, 0 },
+ { 0x188, 34, 1 },
+ { 0x188, 34, 2 },
+ { 0x188, 34, 3 },
+ { 0x188, 34, 4 },
+ { 0x188, 34, 5 },
+ { 0x188, 34, 6 },
+ { 0x188, 34, 7 },
+
+ { 0x188, 35, 0 },
+ { 0x188, 35, 1 },
+ { 0x188, 35, 2 },
+ { 0x188, 35, 3 },
+
+ /* dma 0 */
+ { 0x188, 40, 0 },
+ { 0x188, 40, 1 },
+ { 0x188, 40, 2 },
+ { 0x188, 40, 3 },
+ { 0x188, 40, 4 },
+ { 0x188, 40, 5 },
+ { 0x188, 40, 6 },
+ { 0x188, 40, 7 },
+
+ { 0x188, 41, 0 },
+ { 0x188, 41, 1 },
+ { 0x188, 41, 2 },
+ { 0x188, 41, 3 },
+ { 0x188, 41, 4 },
+ { 0x188, 41, 5 },
+ { 0x188, 41, 6 },
+ { 0x188, 41, 7 },
+
+ { 0x188, 42, 0 },
+ { 0x188, 42, 1 },
+ { 0x188, 42, 2 },
+ { 0x188, 42, 3 },
+ { 0x188, 42, 4 },
+ { 0x188, 42, 5 },
+ { 0x188, 42, 6 },
+ { 0x188, 42, 7 },
+
+ { 0x188, 44, 0 },
+ { 0x188, 44, 1 },
+ { 0x188, 44, 2 },
+ { 0x188, 44, 3 },
+ { 0x188, 44, 4 },
+ { 0x188, 44, 5 },
+ { 0x188, 44, 6 },
+ { 0x188, 44, 7 },
+
+ { 0x188, 45, 0 },
+ { 0x188, 45, 1 },
+ { 0x188, 45, 2 },
+ { 0x188, 45, 3 },
+ { 0x188, 45, 4 },
+ { 0x188, 45, 5 },
+ { 0x188, 45, 6 },
+ { 0x188, 45, 7 },
+
+ /* fetch sspp1 */
+ /* vig 1 */
+ { 0x298, 0, 0 },
+ { 0x298, 0, 1 },
+ { 0x298, 0, 2 },
+ { 0x298, 0, 3 },
+ { 0x298, 0, 4 },
+ { 0x298, 0, 5 },
+ { 0x298, 0, 6 },
+ { 0x298, 0, 7 },
+
+ { 0x298, 1, 0 },
+ { 0x298, 1, 1 },
+ { 0x298, 1, 2 },
+ { 0x298, 1, 3 },
+ { 0x298, 1, 4 },
+ { 0x298, 1, 5 },
+ { 0x298, 1, 6 },
+ { 0x298, 1, 7 },
+
+ { 0x298, 2, 0 },
+ { 0x298, 2, 1 },
+ { 0x298, 2, 2 },
+ { 0x298, 2, 3 },
+ { 0x298, 2, 4 },
+ { 0x298, 2, 5 },
+ { 0x298, 2, 6 },
+ { 0x298, 2, 7 },
+
+ { 0x298, 4, 0 },
+ { 0x298, 4, 1 },
+ { 0x298, 4, 2 },
+ { 0x298, 4, 3 },
+ { 0x298, 4, 4 },
+ { 0x298, 4, 5 },
+ { 0x298, 4, 6 },
+ { 0x298, 4, 7 },
+
+ { 0x298, 5, 0 },
+ { 0x298, 5, 1 },
+ { 0x298, 5, 2 },
+ { 0x298, 5, 3 },
+ { 0x298, 5, 4 },
+ { 0x298, 5, 5 },
+ { 0x298, 5, 6 },
+ { 0x298, 5, 7 },
+
+ /* vig 3 */
+ { 0x298, 20, 0 },
+ { 0x298, 20, 1 },
+ { 0x298, 20, 2 },
+ { 0x298, 20, 3 },
+ { 0x298, 20, 4 },
+ { 0x298, 20, 5 },
+ { 0x298, 20, 6 },
+ { 0x298, 20, 7 },
+
+ { 0x298, 21, 0 },
+ { 0x298, 21, 1 },
+ { 0x298, 21, 2 },
+ { 0x298, 21, 3 },
+ { 0x298, 21, 4 },
+ { 0x298, 21, 5 },
+ { 0x298, 21, 6 },
+ { 0x298, 21, 7 },
+
+ { 0x298, 22, 0 },
+ { 0x298, 22, 1 },
+ { 0x298, 22, 2 },
+ { 0x298, 22, 3 },
+ { 0x298, 22, 4 },
+ { 0x298, 22, 5 },
+ { 0x298, 22, 6 },
+ { 0x298, 22, 7 },
+
+ { 0x298, 24, 0 },
+ { 0x298, 24, 1 },
+ { 0x298, 24, 2 },
+ { 0x298, 24, 3 },
+ { 0x298, 24, 4 },
+ { 0x298, 24, 5 },
+ { 0x298, 24, 6 },
+ { 0x298, 24, 7 },
+
+ { 0x298, 25, 0 },
+ { 0x298, 25, 1 },
+ { 0x298, 25, 2 },
+ { 0x298, 25, 3 },
+ { 0x298, 25, 4 },
+ { 0x298, 25, 5 },
+ { 0x298, 25, 6 },
+ { 0x298, 25, 7 },
+
+ /* dma 3 */
+ { 0x298, 30, 0 },
+ { 0x298, 30, 1 },
+ { 0x298, 30, 2 },
+ { 0x298, 30, 3 },
+ { 0x298, 30, 4 },
+ { 0x298, 30, 5 },
+ { 0x298, 30, 6 },
+ { 0x298, 30, 7 },
+
+ { 0x298, 31, 0 },
+ { 0x298, 31, 1 },
+ { 0x298, 31, 2 },
+ { 0x298, 31, 3 },
+ { 0x298, 31, 4 },
+ { 0x298, 31, 5 },
+ { 0x298, 31, 6 },
+ { 0x298, 31, 7 },
+
+ { 0x298, 32, 0 },
+ { 0x298, 32, 1 },
+ { 0x298, 32, 2 },
+ { 0x298, 32, 3 },
+ { 0x298, 32, 4 },
+ { 0x298, 32, 5 },
+ { 0x298, 32, 6 },
+ { 0x298, 32, 7 },
+
+ { 0x298, 33, 0 },
+ { 0x298, 33, 1 },
+ { 0x298, 33, 2 },
+ { 0x298, 33, 3 },
+ { 0x298, 33, 4 },
+ { 0x298, 33, 5 },
+ { 0x298, 33, 6 },
+ { 0x298, 33, 7 },
+
+ { 0x298, 34, 0 },
+ { 0x298, 34, 1 },
+ { 0x298, 34, 2 },
+ { 0x298, 34, 3 },
+ { 0x298, 34, 4 },
+ { 0x298, 34, 5 },
+ { 0x298, 34, 6 },
+ { 0x298, 34, 7 },
+
+ { 0x298, 35, 0 },
+ { 0x298, 35, 1 },
+ { 0x298, 35, 2 },
+
+ /* dma 1 */
+ { 0x298, 40, 0 },
+ { 0x298, 40, 1 },
+ { 0x298, 40, 2 },
+ { 0x298, 40, 3 },
+ { 0x298, 40, 4 },
+ { 0x298, 40, 5 },
+ { 0x298, 40, 6 },
+ { 0x298, 40, 7 },
+
+ { 0x298, 41, 0 },
+ { 0x298, 41, 1 },
+ { 0x298, 41, 2 },
+ { 0x298, 41, 3 },
+ { 0x298, 41, 4 },
+ { 0x298, 41, 5 },
+ { 0x298, 41, 6 },
+ { 0x298, 41, 7 },
+
+ { 0x298, 42, 0 },
+ { 0x298, 42, 1 },
+ { 0x298, 42, 2 },
+ { 0x298, 42, 3 },
+ { 0x298, 42, 4 },
+ { 0x298, 42, 5 },
+ { 0x298, 42, 6 },
+ { 0x298, 42, 7 },
+
+ { 0x298, 44, 0 },
+ { 0x298, 44, 1 },
+ { 0x298, 44, 2 },
+ { 0x298, 44, 3 },
+ { 0x298, 44, 4 },
+ { 0x298, 44, 5 },
+ { 0x298, 44, 6 },
+ { 0x298, 44, 7 },
+
+ { 0x298, 45, 0 },
+ { 0x298, 45, 1 },
+ { 0x298, 45, 2 },
+ { 0x298, 45, 3 },
+ { 0x298, 45, 4 },
+ { 0x298, 45, 5 },
+ { 0x298, 45, 6 },
+ { 0x298, 45, 7 },
+
+ /* cursor 1 */
+ { 0x298, 80, 0 },
+ { 0x298, 80, 1 },
+ { 0x298, 80, 2 },
+ { 0x298, 80, 3 },
+ { 0x298, 80, 4 },
+ { 0x298, 80, 5 },
+ { 0x298, 80, 6 },
+ { 0x298, 80, 7 },
+
+ { 0x298, 81, 0 },
+ { 0x298, 81, 1 },
+ { 0x298, 81, 2 },
+ { 0x298, 81, 3 },
+ { 0x298, 81, 4 },
+ { 0x298, 81, 5 },
+ { 0x298, 81, 6 },
+ { 0x298, 81, 7 },
+
+ { 0x298, 82, 0 },
+ { 0x298, 82, 1 },
+ { 0x298, 82, 2 },
+ { 0x298, 82, 3 },
+ { 0x298, 82, 4 },
+ { 0x298, 82, 5 },
+ { 0x298, 82, 6 },
+ { 0x298, 82, 7 },
+
+ { 0x298, 83, 0 },
+ { 0x298, 83, 1 },
+ { 0x298, 83, 2 },
+ { 0x298, 83, 3 },
+ { 0x298, 83, 4 },
+ { 0x298, 83, 5 },
+ { 0x298, 83, 6 },
+ { 0x298, 83, 7 },
+
+ { 0x298, 84, 0 },
+ { 0x298, 84, 1 },
+ { 0x298, 84, 2 },
+ { 0x298, 84, 3 },
+ { 0x298, 84, 4 },
+ { 0x298, 84, 5 },
+ { 0x298, 84, 6 },
+ { 0x298, 84, 7 },
+
+ /* dspp */
+ { 0x348, 13, 0 },
+ { 0x348, 19, 0 },
+ { 0x348, 14, 0 },
+ { 0x348, 14, 1 },
+ { 0x348, 14, 3 },
+ { 0x348, 20, 0 },
+ { 0x348, 20, 1 },
+ { 0x348, 20, 3 },
+
+ /* ppb_0 */
+ { 0x348, 31, 0 },
+ { 0x348, 33, 0 },
+ { 0x348, 35, 0 },
+ { 0x348, 42, 0 },
+
+ /* ppb_1 */
+ { 0x348, 32, 0 },
+ { 0x348, 34, 0 },
+ { 0x348, 36, 0 },
+ { 0x348, 43, 0 },
+
+ /* lm_lut */
+ { 0x348, 109, 0 },
+ { 0x348, 105, 0 },
+ { 0x348, 103, 0 },
+
+ /* tear-check */
+ { 0x418, 63, 0 },
+ { 0x418, 64, 0 },
+ { 0x418, 65, 0 },
+ { 0x418, 73, 0 },
+ { 0x418, 74, 0 },
+
+ /* crossbar */
+ { 0x348, 0, 0},
+
+ /* rotator */
+ { 0x348, 9, 0},
+
+ /* blend */
+ /* LM0 */
+ { 0x348, 63, 0},
+ { 0x348, 63, 1},
+ { 0x348, 63, 2},
+ { 0x348, 63, 3},
+ { 0x348, 63, 4},
+ { 0x348, 63, 5},
+ { 0x348, 63, 6},
+ { 0x348, 63, 7},
+
+ { 0x348, 64, 0},
+ { 0x348, 64, 1},
+ { 0x348, 64, 2},
+ { 0x348, 64, 3},
+ { 0x348, 64, 4},
+ { 0x348, 64, 5},
+ { 0x348, 64, 6},
+ { 0x348, 64, 7},
+
+ { 0x348, 65, 0},
+ { 0x348, 65, 1},
+ { 0x348, 65, 2},
+ { 0x348, 65, 3},
+ { 0x348, 65, 4},
+ { 0x348, 65, 5},
+ { 0x348, 65, 6},
+ { 0x348, 65, 7},
+
+ { 0x348, 66, 0},
+ { 0x348, 66, 1},
+ { 0x348, 66, 2},
+ { 0x348, 66, 3},
+ { 0x348, 66, 4},
+ { 0x348, 66, 5},
+ { 0x348, 66, 6},
+ { 0x348, 66, 7},
+
+ { 0x348, 67, 0},
+ { 0x348, 67, 1},
+ { 0x348, 67, 2},
+ { 0x348, 67, 3},
+ { 0x348, 67, 4},
+ { 0x348, 67, 5},
+ { 0x348, 67, 6},
+ { 0x348, 67, 7},
+
+ { 0x348, 68, 0},
+ { 0x348, 68, 1},
+ { 0x348, 68, 2},
+ { 0x348, 68, 3},
+ { 0x348, 68, 4},
+ { 0x348, 68, 5},
+ { 0x348, 68, 6},
+ { 0x348, 68, 7},
+
+ { 0x348, 69, 0},
+ { 0x348, 69, 1},
+ { 0x348, 69, 2},
+ { 0x348, 69, 3},
+ { 0x348, 69, 4},
+ { 0x348, 69, 5},
+ { 0x348, 69, 6},
+ { 0x348, 69, 7},
+
+ /* LM1 */
+ { 0x348, 70, 0},
+ { 0x348, 70, 1},
+ { 0x348, 70, 2},
+ { 0x348, 70, 3},
+ { 0x348, 70, 4},
+ { 0x348, 70, 5},
+ { 0x348, 70, 6},
+ { 0x348, 70, 7},
+
+ { 0x348, 71, 0},
+ { 0x348, 71, 1},
+ { 0x348, 71, 2},
+ { 0x348, 71, 3},
+ { 0x348, 71, 4},
+ { 0x348, 71, 5},
+ { 0x348, 71, 6},
+ { 0x348, 71, 7},
+
+ { 0x348, 72, 0},
+ { 0x348, 72, 1},
+ { 0x348, 72, 2},
+ { 0x348, 72, 3},
+ { 0x348, 72, 4},
+ { 0x348, 72, 5},
+ { 0x348, 72, 6},
+ { 0x348, 72, 7},
+
+ { 0x348, 73, 0},
+ { 0x348, 73, 1},
+ { 0x348, 73, 2},
+ { 0x348, 73, 3},
+ { 0x348, 73, 4},
+ { 0x348, 73, 5},
+ { 0x348, 73, 6},
+ { 0x348, 73, 7},
+
+ { 0x348, 74, 0},
+ { 0x348, 74, 1},
+ { 0x348, 74, 2},
+ { 0x348, 74, 3},
+ { 0x348, 74, 4},
+ { 0x348, 74, 5},
+ { 0x348, 74, 6},
+ { 0x348, 74, 7},
+
+ { 0x348, 75, 0},
+ { 0x348, 75, 1},
+ { 0x348, 75, 2},
+ { 0x348, 75, 3},
+ { 0x348, 75, 4},
+ { 0x348, 75, 5},
+ { 0x348, 75, 6},
+ { 0x348, 75, 7},
+
+ { 0x348, 76, 0},
+ { 0x348, 76, 1},
+ { 0x348, 76, 2},
+ { 0x348, 76, 3},
+ { 0x348, 76, 4},
+ { 0x348, 76, 5},
+ { 0x348, 76, 6},
+ { 0x348, 76, 7},
+
+ /* LM2 */
+ { 0x348, 77, 0},
+ { 0x348, 77, 1},
+ { 0x348, 77, 2},
+ { 0x348, 77, 3},
+ { 0x348, 77, 4},
+ { 0x348, 77, 5},
+ { 0x348, 77, 6},
+ { 0x348, 77, 7},
+
+ { 0x348, 78, 0},
+ { 0x348, 78, 1},
+ { 0x348, 78, 2},
+ { 0x348, 78, 3},
+ { 0x348, 78, 4},
+ { 0x348, 78, 5},
+ { 0x348, 78, 6},
+ { 0x348, 78, 7},
+
+ { 0x348, 79, 0},
+ { 0x348, 79, 1},
+ { 0x348, 79, 2},
+ { 0x348, 79, 3},
+ { 0x348, 79, 4},
+ { 0x348, 79, 5},
+ { 0x348, 79, 6},
+ { 0x348, 79, 7},
+
+ { 0x348, 80, 0},
+ { 0x348, 80, 1},
+ { 0x348, 80, 2},
+ { 0x348, 80, 3},
+ { 0x348, 80, 4},
+ { 0x348, 80, 5},
+ { 0x348, 80, 6},
+ { 0x348, 80, 7},
+
+ { 0x348, 81, 0},
+ { 0x348, 81, 1},
+ { 0x348, 81, 2},
+ { 0x348, 81, 3},
+ { 0x348, 81, 4},
+ { 0x348, 81, 5},
+ { 0x348, 81, 6},
+ { 0x348, 81, 7},
+
+ { 0x348, 82, 0},
+ { 0x348, 82, 1},
+ { 0x348, 82, 2},
+ { 0x348, 82, 3},
+ { 0x348, 82, 4},
+ { 0x348, 82, 5},
+ { 0x348, 82, 6},
+ { 0x348, 82, 7},
+
+ { 0x348, 83, 0},
+ { 0x348, 83, 1},
+ { 0x348, 83, 2},
+ { 0x348, 83, 3},
+ { 0x348, 83, 4},
+ { 0x348, 83, 5},
+ { 0x348, 83, 6},
+ { 0x348, 83, 7},
+
+ /* csc */
+ {0x188, 7, 0},
+ {0x188, 7, 1},
+ {0x188, 27, 0},
+ {0x188, 27, 1},
+ {0x298, 7, 0},
+ {0x298, 7, 1},
+ {0x298, 27, 0},
+ {0x298, 27, 1},
+
+ /* pcc */
+ { 0x188, 3, 3},
+ { 0x188, 23, 3},
+ { 0x188, 33, 3},
+ { 0x188, 43, 3},
+ { 0x298, 3, 3},
+ { 0x298, 23, 3},
+ { 0x298, 33, 3},
+ { 0x298, 43, 3},
+
+ /* spa */
+ { 0x188, 8, 0},
+ { 0x188, 28, 0},
+ { 0x298, 8, 0},
+ { 0x298, 28, 0},
+ { 0x348, 13, 0},
+ { 0x348, 19, 0},
+
+ /* igc */
+ { 0x188, 9, 0},
+ { 0x188, 9, 1},
+ { 0x188, 9, 3},
+ { 0x188, 29, 0},
+ { 0x188, 29, 1},
+ { 0x188, 29, 3},
+ { 0x188, 17, 0},
+ { 0x188, 17, 1},
+ { 0x188, 17, 3},
+ { 0x188, 37, 0},
+ { 0x188, 37, 1},
+ { 0x188, 37, 3},
+ { 0x188, 46, 0},
+ { 0x188, 46, 1},
+ { 0x188, 46, 3},
+
+ { 0x298, 9, 0},
+ { 0x298, 9, 1},
+ { 0x298, 9, 3},
+ { 0x298, 29, 0},
+ { 0x298, 29, 1},
+ { 0x298, 29, 3},
+ { 0x298, 17, 0},
+ { 0x298, 17, 1},
+ { 0x298, 17, 3},
+ { 0x298, 37, 0},
+ { 0x298, 37, 1},
+ { 0x298, 37, 3},
+ { 0x298, 46, 0},
+ { 0x298, 46, 1},
+ { 0x298, 46, 3},
+
+ { 0x348, 14, 0},
+ { 0x348, 14, 1},
+ { 0x348, 14, 3},
+ { 0x348, 20, 0},
+ { 0x348, 20, 1},
+ { 0x348, 20, 3},
+
+ { 0x418, 60, 0},
+};
+
+
static struct vbif_debug_bus vbif_dbg_bus_8996[] = {
{0x214, 0x21c, 16, 2, 0x10}, /* arb clients */
{0x214, 0x21c, 0, 14, 0x13}, /* xin blocks - axi side */
@@ -953,6 +1732,7 @@ void mdss_mdp_hw_rev_debug_caps_init(struct mdss_data_type *mdata)
{
mdata->dbg_bus = NULL;
mdata->dbg_bus_size = 0;
+ mdata->dbg_bus_flags = 0;
switch (mdata->mdp_rev) {
case MDSS_MDP_HW_REV_107:
@@ -966,6 +1746,17 @@ void mdss_mdp_hw_rev_debug_caps_init(struct mdss_data_type *mdata)
mdata->nrt_vbif_dbg_bus_size =
ARRAY_SIZE(nrt_vbif_dbg_bus_8996);
break;
+ case MDSS_MDP_HW_REV_300:
+ case MDSS_MDP_HW_REV_301:
+ mdata->dbg_bus = dbg_bus_msmcobalt;
+ mdata->dbg_bus_size = ARRAY_SIZE(dbg_bus_msmcobalt);
+ mdata->vbif_dbg_bus = vbif_dbg_bus_8996;
+ mdata->vbif_dbg_bus_size = ARRAY_SIZE(vbif_dbg_bus_8996);
+ mdata->nrt_vbif_dbg_bus = nrt_vbif_dbg_bus_8996;
+ mdata->nrt_vbif_dbg_bus_size =
+ ARRAY_SIZE(nrt_vbif_dbg_bus_8996);
+ mdata->dbg_bus_flags = DEBUG_FLAGS_DSPP;
+ break;
default:
break;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_hwio.h b/drivers/video/fbdev/msm/mdss_mdp_hwio.h
index de868bcd8f6f..f54cbb575535 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_hwio.h
+++ b/drivers/video/fbdev/msm/mdss_mdp_hwio.h
@@ -819,6 +819,8 @@ enum mdss_mdp_pingpong_index {
#define MDSS_MDP_REG_CDM_HDMI_PACK_OP_MODE 0x200
+#define MDSS_MDP_DSPP_DEBUGBUS_STATUS 0x34C
+
/* Following offsets are with respect to MDP base */
#define MDSS_MDP_MDP_OUT_CTL_0 0x410
#define MDSS_MDP_INTF_CMD_MISR_CTRL (MDSS_MDP_INTF_MISR_CTRL + 0x8)
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
index a1e5982bccda..0779f7e7afae 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
@@ -1835,6 +1835,26 @@ int mdss_mdp_cmd_reconfigure_splash_done(struct mdss_mdp_ctl *ctl,
return ret;
}
+static int __mdss_mdp_wait4pingpong(struct mdss_mdp_cmd_ctx *ctx)
+{
+ int rc = 0;
+ s64 expected_time = ktime_to_ms(ktime_get()) + KOFF_TIMEOUT_MS;
+ s64 time;
+
+ do {
+ rc = wait_event_timeout(ctx->pp_waitq,
+ atomic_read(&ctx->koff_cnt) == 0,
+ KOFF_TIMEOUT);
+ time = ktime_to_ms(ktime_get());
+
+ MDSS_XLOG(rc, time, expected_time, atomic_read(&ctx->koff_cnt));
+ /* If we timed out, counter is valid and time is less, wait again */
+ } while (atomic_read(&ctx->koff_cnt) && (rc == 0) &&
+ (time < expected_time));
+
+ return rc;
+}
+
static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
{
struct mdss_mdp_cmd_ctx *ctx;
@@ -1856,9 +1876,7 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
pr_debug("%s: intf_num=%d ctx=%p koff_cnt=%d\n", __func__,
ctl->intf_num, ctx, atomic_read(&ctx->koff_cnt));
- rc = wait_event_timeout(ctx->pp_waitq,
- atomic_read(&ctx->koff_cnt) == 0,
- KOFF_TIMEOUT);
+ rc = __mdss_mdp_wait4pingpong(ctx);
trace_mdp_cmd_wait_pingpong(ctl->num,
atomic_read(&ctx->koff_cnt));
@@ -2526,6 +2544,11 @@ static int mdss_mdp_disable_autorefresh(struct mdss_mdp_ctl *ctl,
/* disable autorefresh */
mdss_mdp_pingpong_write(pp_base, MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG, 0);
+
+ if (is_pingpong_split(ctl->mfd))
+ mdss_mdp_pingpong_write(mdata->slave_pingpong_base,
+ MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG, 0);
+
ctx->autorefresh_state = MDP_AUTOREFRESH_OFF;
ctx->autorefresh_frame_cnt = 0;
@@ -2543,6 +2566,9 @@ static int mdss_mdp_disable_autorefresh(struct mdss_mdp_ctl *ctl,
static void __mdss_mdp_kickoff(struct mdss_mdp_ctl *ctl,
struct mdss_mdp_cmd_ctx *ctx)
{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ bool is_pp_split = is_pingpong_split(ctl->mfd);
+
MDSS_XLOG(ctx->autorefresh_state);
if ((ctx->autorefresh_state == MDP_AUTOREFRESH_ON_REQUESTED) ||
@@ -2555,8 +2581,14 @@ static void __mdss_mdp_kickoff(struct mdss_mdp_ctl *ctl,
mdss_mdp_pingpong_write(ctl->mixer_left->pingpong_base,
MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG,
BIT(31) | ctx->autorefresh_frame_cnt);
+
+ if (is_pp_split)
+ mdss_mdp_pingpong_write(mdata->slave_pingpong_base,
+ MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG,
+ BIT(31) | ctx->autorefresh_frame_cnt);
+
MDSS_XLOG(0x11, ctx->autorefresh_frame_cnt,
- ctx->autorefresh_state);
+ ctx->autorefresh_state, is_pp_split);
ctx->autorefresh_state = MDP_AUTOREFRESH_ON;
} else {
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c
index 35bd0932f321..3a39d4fdc895 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c
@@ -1062,7 +1062,6 @@ static struct sync_fence *__create_fence(struct msm_fb_data_type *mfd,
goto end;
}
- sync_fence_install(sync_fence, *fence_fd);
end:
return sync_fence;
}
@@ -1136,6 +1135,9 @@ static int __handle_buffer_fences(struct msm_fb_data_type *mfd,
goto retire_fence_err;
}
+ sync_fence_install(release_fence, commit->release_fence);
+ sync_fence_install(retire_fence, commit->retire_fence);
+
mutex_unlock(&sync_pt_data->sync_mutex);
return ret;
diff --git a/drivers/video/fbdev/msm/mdss_smmu.c b/drivers/video/fbdev/msm/mdss_smmu.c
index 9906f10a7911..9a00eff9ade9 100644
--- a/drivers/video/fbdev/msm/mdss_smmu.c
+++ b/drivers/video/fbdev/msm/mdss_smmu.c
@@ -172,6 +172,7 @@ static int mdss_smmu_attach_v2(struct mdss_data_type *mdata)
struct mdss_smmu_client *mdss_smmu;
int i, rc = 0;
+ mutex_lock(&mdp_iommu_lock);
for (i = 0; i < MDSS_IOMMU_MAX_DOMAIN; i++) {
if (!mdss_smmu_is_valid_domain_type(mdata, i))
continue;
@@ -203,9 +204,12 @@ static int mdss_smmu_attach_v2(struct mdss_data_type *mdata)
}
} else {
pr_err("iommu device not attached for domain[%d]\n", i);
+ mutex_unlock(&mdp_iommu_lock);
return -ENODEV;
}
}
+ mutex_unlock(&mdp_iommu_lock);
+
return 0;
err:
@@ -217,6 +221,8 @@ err:
mdss_smmu->domain_attached = false;
}
}
+ mutex_unlock(&mdp_iommu_lock);
+
return rc;
}
@@ -231,6 +237,7 @@ static int mdss_smmu_detach_v2(struct mdss_data_type *mdata)
struct mdss_smmu_client *mdss_smmu;
int i;
+ mutex_lock(&mdp_iommu_lock);
for (i = 0; i < MDSS_IOMMU_MAX_DOMAIN; i++) {
if (!mdss_smmu_is_valid_domain_type(mdata, i))
continue;
@@ -239,6 +246,8 @@ static int mdss_smmu_detach_v2(struct mdss_data_type *mdata)
if (mdss_smmu && mdss_smmu->dev && !mdss_smmu->handoff_pending)
mdss_smmu_enable_power(mdss_smmu, false);
}
+ mutex_unlock(&mdp_iommu_lock);
+
return 0;
}
diff --git a/include/dt-bindings/clock/msm-clocks-8996.h b/include/dt-bindings/clock/msm-clocks-8996.h
index 2f9cfd0e008c..22109a6766db 100644
--- a/include/dt-bindings/clock/msm-clocks-8996.h
+++ b/include/dt-bindings/clock/msm-clocks-8996.h
@@ -540,4 +540,33 @@
#define clk_sys_apcsaux_clk 0x0b0dd513
#define clk_cpu_debug_mux 0xc7acaa31
+/* GCC block resets */
+#define QUSB2PHY_PRIM_BCR 0
+#define QUSB2PHY_SEC_BCR 1
+#define BLSP1_BCR 2
+#define BLSP2_BCR 3
+#define BOOT_ROM_BCR 4
+#define PRNG_BCR 5
+#define UFS_BCR 6
+#define USB_20_BCR 7
+#define USB_30_BCR 8
+#define USB3_PHY_BCR 9
+#define USB3PHY_PHY_BCR 10
+#define PCIE_0_PHY_BCR 11
+#define PCIE_1_PHY_BCR 12
+#define PCIE_2_PHY_BCR 13
+#define PCIE_PHY_BCR 14
+#define PCIE_PHY_COM_BCR 15
+#define PCIE_PHY_NOCSR_COM_PHY_BCR 16
+
+/* MMSS Block resets */
+#define VIDEO_BCR 0
+#define MDSS_BCR 1
+#define CAMSS_MICRO_BCR 2
+#define CAMSS_JPEG_BCR 3
+#define CAMSS_VFE0_BCR 4
+#define CAMSS_VFE1_BCR 5
+#define FD_BCR 6
+#define GPU_GX_BCR 7
+
#endif
diff --git a/include/dt-bindings/clock/qcom,gcc-msmfalcon.h b/include/dt-bindings/clock/qcom,gcc-msmfalcon.h
index d0a8419ee54c..6860d78e020e 100644
--- a/include/dt-bindings/clock/qcom,gcc-msmfalcon.h
+++ b/include/dt-bindings/clock/qcom,gcc-msmfalcon.h
@@ -14,230 +14,229 @@
#ifndef _DT_BINDINGS_CLK_MSM_GCC_FALCON_H
#define _DT_BINDINGS_CLK_MSM_GCC_FALCON_H
-/* Clocks */
-#define GPLL0 0
-#define GPLL1 1
-#define GPLL2 2
-#define GPLL3 3
-#define GPLL4 4
-#define GPLL5 5
-#define GPLL6 6
-#define MMSS_QM_CORE_CLK_SRC 7
-#define USB30_MASTER_CLK_SRC 8
-#define USB30_MOCK_UTMI_CLK_SRC 9
-#define USB3_PHY_AUX_CLK_SRC 10
-#define USB20_MASTER_CLK_SRC 11
-#define USB20_MOCK_UTMI_CLK_SRC 12
-#define SDCC2_APPS_CLK_SRC 13
-#define SDCC1_ICE_CORE_CLK_SRC 14
-#define SDCC1_APPS_CLK_SRC 15
-#define BLSP1_QUP1_SPI_APPS_CLK_SRC 16
-#define BLSP1_QUP1_I2C_APPS_CLK_SRC 17
-#define BLSP1_UART1_APPS_CLK_SRC 18
-#define BLSP1_QUP2_SPI_APPS_CLK_SRC 19
-#define BLSP1_QUP2_I2C_APPS_CLK_SRC 20
-#define BLSP1_UART2_APPS_CLK_SRC 21
-#define BLSP1_QUP3_SPI_APPS_CLK_SRC 22
-#define BLSP1_QUP3_I2C_APPS_CLK_SRC 23
-#define BLSP1_QUP4_SPI_APPS_CLK_SRC 24
-#define BLSP1_QUP4_I2C_APPS_CLK_SRC 25
-#define BLSP2_QUP1_SPI_APPS_CLK_SRC 26
-#define BLSP2_QUP1_I2C_APPS_CLK_SRC 27
-#define BLSP2_UART1_APPS_CLK_SRC 28
-#define BLSP2_QUP2_SPI_APPS_CLK_SRC 29
-#define BLSP2_QUP2_I2C_APPS_CLK_SRC 30
-#define BLSP2_UART2_APPS_CLK_SRC 31
-#define BLSP2_QUP3_SPI_APPS_CLK_SRC 32
-#define BLSP2_QUP3_I2C_APPS_CLK_SRC 33
-#define BLSP2_QUP4_SPI_APPS_CLK_SRC 34
-#define BLSP2_QUP4_I2C_APPS_CLK_SRC 35
-#define PDM2_CLK_SRC 36
-#define HMSS_AHB_CLK_SRC 37
-#define BIMC_HMSS_AXI_CLK_SRC 38
-#define HMSS_RBCPR_CLK_SRC 39
-#define HMSS_GPLL0_CLK_SRC 40
-#define HMSS_GPLL4_CLK_SRC 41
-#define GP1_CLK_SRC 42
-#define GP2_CLK_SRC 43
-#define GP3_CLK_SRC 44
-#define UFS_AXI_CLK_SRC 45
-#define UFS_ICE_CORE_CLK_SRC 46
-#define UFS_UNIPRO_CORE_CLK_SRC 47
-#define UFS_PHY_AUX_CLK_SRC 48
-#define QSPI_SER_CLK_SRC 49
-#define GLM_CLK_SRC 50
-#define GCC_MMSS_SYS_NOC_AXI_CLK 51
-#define GCC_MMSS_NOC_CFG_AHB_CLK 52
-#define GCC_MMSS_QM_CORE_CLK 53
-#define GCC_MMSS_QM_AHB_CLK 54
-#define GCC_USB30_MASTER_CLK 55
-#define GCC_USB30_SLEEP_CLK 56
-#define GCC_USB30_MOCK_UTMI_CLK 57
-#define GCC_USB3_PHY_AUX_CLK 58
-#define GCC_USB3_PHY_PIPE_CLK 59
-#define GCC_USB20_MASTER_CLK 60
-#define GCC_USB20_SLEEP_CLK 61
-#define GCC_USB20_MOCK_UTMI_CLK 62
-#define GCC_USB_PHY_CFG_AHB2PHY_CLK 63
-#define GCC_SDCC2_APPS_CLK 64
-#define GCC_SDCC2_AHB_CLK 65
-#define GCC_SDCC1_APPS_CLK 66
-#define GCC_SDCC1_AHB_CLK 67
-#define GCC_SDCC1_ICE_CORE_CLK 68
-#define GCC_BLSP1_AHB_CLK 69
-#define GCC_BLSP1_SLEEP_CLK 70
-#define GCC_BLSP1_QUP1_SPI_APPS_CLK 71
-#define GCC_BLSP1_QUP1_I2C_APPS_CLK 72
-#define GCC_BLSP1_UART1_APPS_CLK 73
-#define GCC_BLSP1_QUP2_SPI_APPS_CLK 74
-#define GCC_BLSP1_QUP2_I2C_APPS_CLK 75
-#define GCC_BLSP1_UART2_APPS_CLK 76
-#define GCC_BLSP1_QUP3_SPI_APPS_CLK 77
-#define GCC_BLSP1_QUP3_I2C_APPS_CLK 78
-#define GCC_BLSP1_QUP4_SPI_APPS_CLK 79
-#define GCC_BLSP1_QUP4_I2C_APPS_CLK 80
-#define GCC_BLSP2_AHB_CLK 81
-#define GCC_BLSP2_SLEEP_CLK 82
-#define GCC_BLSP2_QUP1_SPI_APPS_CLK 83
-#define GCC_BLSP2_QUP1_I2C_APPS_CLK 84
-#define GCC_BLSP2_UART1_APPS_CLK 85
-#define GCC_BLSP2_QUP2_SPI_APPS_CLK 86
-#define GCC_BLSP2_QUP2_I2C_APPS_CLK 87
-#define GCC_BLSP2_UART2_APPS_CLK 88
-#define GCC_BLSP2_QUP3_SPI_APPS_CLK 89
-#define GCC_BLSP2_QUP3_I2C_APPS_CLK 90
-#define GCC_BLSP2_QUP4_SPI_APPS_CLK 91
-#define GCC_BLSP2_QUP4_I2C_APPS_CLK 92
-#define GCC_PDM_AHB_CLK 93
-#define GCC_PDM_XO4_CLK 94
-#define GCC_PDM2_CLK 95
-#define GCC_PRNG_AHB_CLK 96
-#define GCC_BIMC_GFX_CLK 97
-#define GCC_MCCC_CFG_AHB_CLK 98
-#define GCC_LPASS_TRIG_CLK 99
-#define GCC_LPASS_AT_CLK 100
-#define GCC_TURING_TRIG_CLK 101
-#define GCC_TURING_AT_CLK 102
-#define GCC_HMSS_AHB_CLK 103
-#define GCC_BIMC_HMSS_AXI_CLK 104
-#define GCC_HMSS_RBCPR_CLK 105
-#define GCC_HMSS_TRIG_CLK 106
-#define GCC_HMSS_AT_CLK 107
-#define GCC_HMSS_DVM_BUS_CLK 108
-#define GCC_GP1_CLK 109
-#define GCC_GP2_CLK 110
-#define GCC_GP3_CLK 111
-#define GCC_UFS_AXI_CLK 112
-#define GCC_UFS_AHB_CLK 113
-#define GCC_UFS_TX_SYMBOL_0_CLK 114
-#define GCC_UFS_RX_SYMBOL_0_CLK 115
-#define GCC_UFS_UNIPRO_CORE_CLK 116
-#define GCC_UFS_ICE_CORE_CLK 117
-#define GCC_UFS_PHY_AUX_CLK 118
-#define GCC_UFS_RX_SYMBOL_1_CLK 119
-#define GCC_AGGRE2_USB3_AXI_CLK 120
-#define GCC_AGGRE2_UFS_AXI_CLK 121
-#define GCC_QSPI_AHB_CLK 122
-#define GCC_QSPI_SER_CLK 123
-#define GCC_GLM_AHB_CLK 124
-#define GCC_GLM_CLK 125
-#define GCC_GLM_XO_CLK 126
-#define GCC_WCSS_AHB_S0_CLK 127
-#define GCC_WCSS_AXI_M_CLK 128
-#define GCC_WCSS_ECAHB_CLK 129
-#define GCC_WCSS_SHDREG_AHB_CLK 130
-#define GCC_GPU_CFG_AHB_CLK 131
-#define GCC_GPU_BIMC_GFX_SRC_CLK 132
-#define GCC_GPU_BIMC_GFX_CLK 133
-#define GCC_GPU_SNOC_DVM_GFX_CLK 134
+#define BIMC_HMSS_AXI_CLK_SRC 0
+#define BLSP1_QUP1_I2C_APPS_CLK_SRC 1
+#define BLSP1_QUP1_SPI_APPS_CLK_SRC 2
+#define BLSP1_QUP2_I2C_APPS_CLK_SRC 3
+#define BLSP1_QUP2_SPI_APPS_CLK_SRC 4
+#define BLSP1_QUP3_I2C_APPS_CLK_SRC 5
+#define BLSP1_QUP3_SPI_APPS_CLK_SRC 6
+#define BLSP1_QUP4_I2C_APPS_CLK_SRC 7
+#define BLSP1_QUP4_SPI_APPS_CLK_SRC 8
+#define BLSP1_UART1_APPS_CLK_SRC 9
+#define BLSP1_UART2_APPS_CLK_SRC 10
+#define BLSP2_QUP1_I2C_APPS_CLK_SRC 11
+#define BLSP2_QUP1_SPI_APPS_CLK_SRC 12
+#define BLSP2_QUP2_I2C_APPS_CLK_SRC 13
+#define BLSP2_QUP2_SPI_APPS_CLK_SRC 14
+#define BLSP2_QUP3_I2C_APPS_CLK_SRC 15
+#define BLSP2_QUP3_SPI_APPS_CLK_SRC 16
+#define BLSP2_QUP4_I2C_APPS_CLK_SRC 17
+#define BLSP2_QUP4_SPI_APPS_CLK_SRC 18
+#define BLSP2_UART1_APPS_CLK_SRC 19
+#define BLSP2_UART2_APPS_CLK_SRC 20
+#define GCC_AGGRE2_UFS_AXI_CLK 21
+#define GCC_AGGRE2_USB3_AXI_CLK 22
+#define GCC_BIMC_GFX_CLK 23
+#define GCC_BIMC_HMSS_AXI_CLK 24
+#define GCC_BIMC_MSS_Q6_AXI_CLK 25
+#define GCC_BLSP1_AHB_CLK 26
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK 27
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK 28
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK 29
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK 30
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK 31
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK 32
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK 33
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK 34
+#define GCC_BLSP1_UART1_APPS_CLK 35
+#define GCC_BLSP1_UART2_APPS_CLK 36
+#define GCC_BLSP2_AHB_CLK 37
+#define GCC_BLSP2_QUP1_I2C_APPS_CLK 38
+#define GCC_BLSP2_QUP1_SPI_APPS_CLK 39
+#define GCC_BLSP2_QUP2_I2C_APPS_CLK 40
+#define GCC_BLSP2_QUP2_SPI_APPS_CLK 41
+#define GCC_BLSP2_QUP3_I2C_APPS_CLK 42
+#define GCC_BLSP2_QUP3_SPI_APPS_CLK 43
+#define GCC_BLSP2_QUP4_I2C_APPS_CLK 44
+#define GCC_BLSP2_QUP4_SPI_APPS_CLK 45
+#define GCC_BLSP2_UART1_APPS_CLK 46
+#define GCC_BLSP2_UART2_APPS_CLK 47
+#define GCC_BOOT_ROM_AHB_CLK 48
+#define GCC_CFG_NOC_USB2_AXI_CLK 49
+#define GCC_CFG_NOC_USB3_AXI_CLK 50
+#define GCC_GLM_AHB_CLK 51
+#define GCC_GLM_CLK 52
+#define GCC_GP1_CLK 53
+#define GCC_GP2_CLK 54
+#define GCC_GP3_CLK 55
+#define GCC_GPU_BIMC_GFX_CLK 56
+#define GCC_GPU_BIMC_GFX_SRC_CLK 57
+#define GCC_GPU_CFG_AHB_CLK 58
+#define GCC_GPU_SNOC_DVM_GFX_CLK 59
+#define GCC_HMSS_AHB_CLK 60
+#define GCC_HMSS_DVM_BUS_CLK 61
+#define GCC_HMSS_RBCPR_CLK 62
+#define GCC_MMSS_NOC_CFG_AHB_CLK 63
+#define GCC_MMSS_QM_AHB_CLK 64
+#define GCC_MMSS_QM_CORE_CLK 65
+#define GCC_MMSS_SYS_NOC_AXI_CLK 66
+#define GCC_PDM2_CLK 67
+#define GCC_PDM_AHB_CLK 68
+#define GCC_PRNG_AHB_CLK 69
+#define GCC_QSPI_AHB_CLK 70
+#define GCC_QSPI_SER_CLK 71
+#define GCC_SDCC1_AHB_CLK 72
+#define GCC_SDCC1_APPS_CLK 73
+#define GCC_SDCC1_ICE_CORE_CLK 74
+#define GCC_SDCC2_AHB_CLK 75
+#define GCC_SDCC2_APPS_CLK 76
+#define GCC_UFS_AHB_CLK 77
+#define GCC_UFS_AXI_CLK 78
+#define GCC_UFS_ICE_CORE_CLK 79
+#define GCC_UFS_PHY_AUX_CLK 80
+#define GCC_UFS_RX_SYMBOL_0_CLK 81
+#define GCC_UFS_RX_SYMBOL_1_CLK 82
+#define GCC_UFS_TX_SYMBOL_0_CLK 83
+#define GCC_UFS_UNIPRO_CORE_CLK 84
+#define GCC_USB20_MASTER_CLK 85
+#define GCC_USB20_MOCK_UTMI_CLK 86
+#define GCC_USB20_SLEEP_CLK 87
+#define GCC_USB30_MASTER_CLK 88
+#define GCC_USB30_MOCK_UTMI_CLK 89
+#define GCC_USB30_SLEEP_CLK 90
+#define GCC_USB3_PHY_AUX_CLK 91
+#define GCC_USB3_PHY_PIPE_CLK 92
+#define GCC_USB_PHY_CFG_AHB2PHY_CLK 93
+#define GCC_WCSS_AHB_S0_CLK 94
+#define GCC_WCSS_AXI_M_CLK 95
+#define GCC_WCSS_ECAHB_CLK 96
+#define GCC_WCSS_SHDREG_AHB_CLK 97
+#define GLM_CLK_SRC 98
+#define GP1_CLK_SRC 99
+#define GP2_CLK_SRC 100
+#define GP3_CLK_SRC 101
+#define GPLL0 102
+#define GPLL0_OUT_AUX 103
+#define GPLL0_OUT_AUX2 104
+#define GPLL0_OUT_EARLY 105
+#define GPLL0_OUT_MAIN 106
+#define GPLL0_OUT_TEST 107
+#define GPLL1 108
+#define GPLL1_OUT_AUX 109
+#define GPLL1_OUT_AUX2 110
+#define GPLL1_OUT_EARLY 111
+#define GPLL1_OUT_MAIN 112
+#define GPLL1_OUT_TEST 113
+#define GPLL2 114
+#define GPLL2_OUT_AUX 115
+#define GPLL2_OUT_AUX2 116
+#define GPLL2_OUT_EARLY 117
+#define GPLL2_OUT_MAIN 118
+#define GPLL2_OUT_TEST 119
+#define GPLL3 120
+#define GPLL3_OUT_AUX 121
+#define GPLL3_OUT_AUX2 122
+#define GPLL3_OUT_EARLY 123
+#define GPLL3_OUT_MAIN 124
+#define GPLL3_OUT_TEST 125
+#define GPLL4 126
+#define GPLL4_OUT_AUX 127
+#define GPLL4_OUT_AUX2 128
+#define GPLL4_OUT_EARLY 129
+#define GPLL4_OUT_MAIN 130
+#define GPLL4_OUT_TEST 131
+#define GPLL5 132
+#define GPLL5_OUT_AUX 133
+#define GPLL5_OUT_AUX2 134
+#define GPLL5_OUT_EARLY 135
+#define GPLL5_OUT_MAIN 136
+#define GPLL5_OUT_TEST 137
+#define GPLL6 138
+#define GPLL6_OUT_AUX 139
+#define GPLL6_OUT_AUX2 140
+#define GPLL6_OUT_EARLY 141
+#define GPLL6_OUT_MAIN 142
+#define GPLL6_OUT_TEST 143
+#define HMSS_AHB_CLK_SRC 144
+#define HMSS_GPLL0_CLK_SRC 145
+#define HMSS_GPLL4_CLK_SRC 146
+#define HMSS_RBCPR_CLK_SRC 147
+#define MMSS_QM_CORE_CLK_SRC 148
+#define PDM2_CLK_SRC 149
+#define QSPI_SER_CLK_SRC 150
+#define SDCC1_APPS_CLK_SRC 151
+#define SDCC1_ICE_CORE_CLK_SRC 152
+#define SDCC2_APPS_CLK_SRC 153
+#define UFS_AXI_CLK_SRC 154
+#define UFS_ICE_CORE_CLK_SRC 155
+#define UFS_PHY_AUX_CLK_SRC 156
+#define UFS_UNIPRO_CORE_CLK_SRC 157
+#define USB20_MASTER_CLK_SRC 158
+#define USB20_MOCK_UTMI_CLK_SRC 159
+#define USB30_MASTER_CLK_SRC 160
+#define USB30_MOCK_UTMI_CLK_SRC 161
+#define USB3_PHY_AUX_CLK_SRC 162
-/* Block Resets */
-#define GCC_SYSTEM_NOC_BCR 0
-#define GCC_CONFIG_NOC_BCR 1
-#define GCC_IMEM_BCR 2
-#define GCC_MMSS_BCR 3
-#define GCC_PIMEM_BCR 4
-#define GCC_QDSS_BCR 5
-#define GCC_USB_30_BCR 6
-#define GCC_USB_20_BCR 7
-#define GCC_QUSB2PHY_PRIM_BCR 8
-#define GCC_QUSB2PHY_SEC_BCR 9
-#define GCC_USB_PHY_CFG_AHB2PHY_BCR 10
-#define GCC_SDCC2_BCR 11
-#define GCC_SDCC1_BCR 12
-#define GCC_BLSP1_BCR 13
-#define GCC_BLSP1_QUP1_BCR 14
-#define GCC_BLSP1_UART1_BCR 15
-#define GCC_BLSP1_QUP2_BCR 16
-#define GCC_BLSP1_UART2_BCR 17
-#define GCC_BLSP1_QUP3_BCR 18
-#define GCC_BLSP1_QUP4_BCR 19
-#define GCC_BLSP2_BCR 20
-#define GCC_BLSP2_QUP1_BCR 21
-#define GCC_BLSP2_UART1_BCR 22
-#define GCC_BLSP2_QUP2_BCR 23
-#define GCC_BLSP2_UART2_BCR 24
-#define GCC_BLSP2_QUP3_BCR 25
-#define GCC_BLSP2_QUP4_BCR 26
-#define GCC_PDM_BCR 27
-#define GCC_PRNG_BCR 28
-#define GCC_TCSR_BCR 29
-#define GCC_BOOT_ROM_BCR 30
-#define GCC_MSG_RAM_BCR 31
-#define GCC_TLMM_BCR 32
-#define GCC_MPM_BCR 33
-#define GCC_SEC_CTRL_BCR 34
-#define GCC_SPMI_BCR 35
-#define GCC_SPDM_BCR 36
-#define GCC_CE1_BCR 37
-#define GCC_BIMC_BCR 38
-#define GCC_SNOC_BUS_TIMEOUT0_BCR 39
-#define GCC_SNOC_BUS_TIMEOUT1_BCR 40
-#define GCC_SNOC_BUS_TIMEOUT3_BCR 41
-#define GCC_SNOC_BUS_TIMEOUT_EXTREF_BCR 42
-#define GCC_SNOC_BUS_TIMEOUT4_BCR 43
-#define GCC_PNOC_BUS_TIMEOUT0_BCR 44
-#define GCC_CNOC_PERIPH_BUS_TIMEOUT1_BCR 45
-#define GCC_CNOC_PERIPH_BUS_TIMEOUT2_BCR 46
-#define GCC_CNOC_BUS_TIMEOUT0_BCR 47
-#define GCC_CNOC_BUS_TIMEOUT2_BCR 48
-#define GCC_CNOC_BUS_TIMEOUT3_BCR 49
-#define GCC_CNOC_BUS_TIMEOUT4_BCR 50
-#define GCC_CNOC_BUS_TIMEOUT5_BCR 51
-#define GCC_CNOC_BUS_TIMEOUT6_BCR 52
-#define GCC_CNOC_BUS_TIMEOUT7_BCR 53
-#define GCC_CNOC_BUS_TIMEOUT8_BCR 54
-#define GCC_CNOC_BUS_TIMEOUT9_BCR 55
-#define GCC_CNOC_BUS_TIMEOUT10_BCR 56
-#define GCC_CNOC_BUS_TIMEOUT11_BCR 57
-#define GCC_CNOC_BUS_TIMEOUT12_BCR 58
-#define GCC_CNOC_BUS_TIMEOUT13_BCR 59
-#define GCC_CNOC_BUS_TIMEOUT14_BCR 60
-#define GCC_CNOC_BUS_TIMEOUT_EXTREF_BCR 61
-#define GCC_APB2JTAG_BCR 62
-#define GCC_RBCPR_CX_BCR 63
-#define GCC_RBCPR_MX_BCR 64
-#define GCC_OBT_ODT_BCR 65
-#define GCC_UFS_BCR 66
-#define GCC_VS_BCR 67
-#define GCC_AGGRE2_NOC_BCR 68
-#define GCC_DCC_BCR 69
-#define GCC_QSPI_BCR 70
-#define GCC_IPA_BCR 71
-#define GCC_GLM_BCR 72
-#define GCC_MSMPU_BCR 73
-#define GCC_QREFS_VBG_CAL_BCR 74
-#define GCC_WCSS_BCR 75
-#define GCC_GPU_BCR 76
-#define GCC_AHB2PHY_EAST_BCR 77
-#define GCC_CM_PHY_REFGEN1_BCR 78
-#define GCC_CM_PHY_REFGEN2_BCR 79
-#define GCC_SRAM_SENSOR_BCR 80
+#define UFS_GDSC 0
+#define USB_30_GDSC 1
-/* GDSC */
-#define UFS_GDSC 0
-#define USB_30_GDSC 1
-#define DDR_DIM_WRAPPER_GDSC 2
-#define MMSS_GDSC 3
+#define GCC_QUSB2PHY_PRIM_BCR 0
+#define GCC_QUSB2PHY_SEC_BCR 1
+#define GCC_UFS_BCR 2
+#define GCC_USB3_DP_PHY_BCR 3
+#define GCC_USB3_PHY_BCR 4
+#define GCC_USB3PHY_PHY_BCR 5
+#define GCC_USB_20_BCR 6
+#define GCC_USB_30_BCR 7
+#define GCC_USB_PHY_CFG_AHB2PHY_BCR 8
+
+/* RPM controlled clocks */
+#define RPM_CE1_CLK 1
+#define RPM_CE1_A_CLK 2
+#define RPM_CXO_CLK_SRC 3
+#define RPM_BIMC_CLK 4
+#define RPM_BIMC_A_CLK 5
+#define RPM_CNOC_CLK 6
+#define RPM_CNOC_A_CLK 7
+#define RPM_SNOC_CLK 8
+#define RPM_SNOC_A_CLK 9
+#define RPM_CNOC_PERIPH_CLK 10
+#define RPM_CNOC_PERIPH_A_CLK 11
+#define RPM_CNOC_PERIPH_KEEPALIVE_A_CLK 12
+#define RPM_LN_BB_CLK1 13
+#define RPM_LN_BB_CLK1_AO 14
+#define RPM_LN_BB_CLK1_PIN 15
+#define RPM_LN_BB_CLK1_PIN_AO 16
+#define RPM_BIMC_MSMBUS_CLK 17
+#define RPM_BIMC_MSMBUS_A_CLK 18
+#define RPM_CNOC_MSMBUS_CLK 19
+#define RPM_CNOC_MSMBUS_A_CLK 20
+#define RPM_CXO_CLK_SRC_AO 21
+#define RPM_CXO_DWC3_CLK 22
+#define RPM_CXO_LPM_CLK 23
+#define RPM_CXO_OTG_CLK 24
+#define RPM_CXO_PIL_LPASS_CLK 25
+#define RPM_CXO_PIL_SSC_CLK 26
+#define RPM_CXO_PIL_SPSS_CLK 27
+#define RPM_DIV_CLK1 28
+#define RPM_DIV_CLK1_AO 29
+#define RPM_IPA_CLK 30
+#define RPM_IPA_A_CLK 31
+#define RPM_MCD_CE1_CLK 32
+#define RPM_MMSSNOC_AXI_CLK 33
+#define RPM_MMSSNOC_AXI_A_CLK 34
+#define RPM_QCEDEV_CE1_CLK 35
+#define RPM_QCRYPTO_CE1_CLK 36
+#define RPM_QDSS_CLK 37
+#define RPM_QDSS_A_CLK 38
+#define RPM_QSEECOM_CE1_CLK 39
+#define RPM_RF_CLK2 40
+#define RPM_RF_CLK2_AO 41
+#define RPM_SCM_CE1_CLK 42
+#define RPM_SNOC_MSMBUS_CLK 43
+#define RPM_SNOC_MSMBUS_A_CLK 44
+#define RPM_AGGRE2_NOC_CLK 45
+#define RPM_AGGRE2_NOC_A_CLK 46
#endif
diff --git a/include/dt-bindings/clock/qcom,gpu-msmfalcon.h b/include/dt-bindings/clock/qcom,gpu-msmfalcon.h
index a167716e9cc6..427c6aae05d3 100644
--- a/include/dt-bindings/clock/qcom,gpu-msmfalcon.h
+++ b/include/dt-bindings/clock/qcom,gpu-msmfalcon.h
@@ -14,25 +14,27 @@
#ifndef _DT_BINDINGS_CLK_MSM_GPU_FALCON_H
#define _DT_BINDINGS_CLK_MSM_GPU_FALCON_H
-/* Clocks */
-#define GPU_PLL0_PLL 0
-#define GPU_PLL1_PLL 1
-#define GFX3D_CLK_SRC 2
-#define RBBMTIMER_CLK_SRC 3
-#define RBCPR_CLK_SRC 4
-#define GPUCC_CXO_CLK 5
-#define GPUCC_GFX3D_CLK 6
-#define GPUCC_RBBMTIMER_CLK 7
-#define GPUCC_RBCPR_CLK 8
+#define GFX3D_CLK_SRC 0
+#define GPU_PLL0_PLL 1
+#define GPU_PLL0_PLL_OUT_AUX 2
+#define GPU_PLL0_PLL_OUT_AUX2 3
+#define GPU_PLL0_PLL_OUT_EARLY 4
+#define GPU_PLL0_PLL_OUT_MAIN 5
+#define GPU_PLL0_PLL_OUT_TEST 6
+#define GPU_PLL1_PLL 7
+#define GPU_PLL1_PLL_OUT_AUX 8
+#define GPU_PLL1_PLL_OUT_AUX2 9
+#define GPU_PLL1_PLL_OUT_EARLY 10
+#define GPU_PLL1_PLL_OUT_MAIN 11
+#define GPU_PLL1_PLL_OUT_TEST 12
+#define GPUCC_CXO_CLK 13
+#define GPUCC_GFX3D_CLK 14
+#define GPUCC_RBBMTIMER_CLK 15
+#define GPUCC_RBCPR_CLK 16
+#define RBBMTIMER_CLK_SRC 18
+#define RBCPR_CLK_SRC 19
-/* Block Reset */
-#define GPU_CC_GPU_GX_BCR 0
-#define GPU_CC_GPU_CX_BCR 1
-#define GPU_CC_RBCPR_BCR 2
-#define GPU_CC_SPDM_BCR 3
-
-/* GDSC */
-#define GPU_GX_GDSC 0
-#define GPU_CX_GDSC 1
+#define GPU_CX_GDSC 0
+#define GPU_GX_GDSC 1
#endif
diff --git a/include/dt-bindings/clock/qcom,mmcc-msmfalcon.h b/include/dt-bindings/clock/qcom,mmcc-msmfalcon.h
index 57aed7c8f43f..ffb80a128dd6 100644
--- a/include/dt-bindings/clock/qcom,mmcc-msmfalcon.h
+++ b/include/dt-bindings/clock/qcom,mmcc-msmfalcon.h
@@ -14,181 +14,200 @@
#ifndef _DT_BINDINGS_CLK_MSM_MMCC_FALCON_H
#define _DT_BINDINGS_CLK_MSM_MMCC_FALCON_H
-/* Clocks */
-#define MMPLL3_PLL 0
-#define MMPLL4_PLL 1
-#define MMPLL5_PLL 2
-#define MMPLL6_PLL 3
-#define MMPLL7_PLL 4
-#define MMPLL8_PLL 5
-#define AHB_CLK_SRC 6
-#define VIDEO_CORE_CLK_SRC 7
-#define PCLK0_CLK_SRC 8
-#define PCLK1_CLK_SRC 9
-#define MDP_CLK_SRC 10
-#define ROT_CLK_SRC 11
-#define VSYNC_CLK_SRC 12
-#define BYTE0_CLK_SRC 13
-#define BYTE1_CLK_SRC 14
-#define ESC0_CLK_SRC 15
-#define ESC1_CLK_SRC 16
-#define DP_LINK_CLK_SRC 17
-#define DP_CRYPTO_CLK_SRC 18
-#define DP_PIXEL_CLK_SRC 19
-#define DP_AUX_CLK_SRC 20
-#define DP_GTC_CLK_SRC 21
-#define CAMSS_GP0_CLK_SRC 22
-#define CAMSS_GP1_CLK_SRC 23
-#define MCLK0_CLK_SRC 24
-#define MCLK1_CLK_SRC 25
-#define MCLK2_CLK_SRC 26
-#define MCLK3_CLK_SRC 27
-#define CCI_CLK_SRC 28
-#define CSI0PHYTIMER_CLK_SRC 29
-#define CSI1PHYTIMER_CLK_SRC 30
-#define CSI2PHYTIMER_CLK_SRC 31
-#define JPEG0_CLK_SRC 32
-#define VFE0_CLK_SRC 33
-#define VFE1_CLK_SRC 34
-#define CPP_CLK_SRC 35
-#define CSIPHY_CLK_SRC 36
-#define CSI0_CLK_SRC 37
-#define CSI1_CLK_SRC 38
-#define CSI2_CLK_SRC 39
-#define CSI3_CLK_SRC 40
-#define MMSS_CXO_CLK 41
-#define MMSS_SLEEP_CLK 42
-#define MMSS_MNOC_AHB_CLK 43
-#define MMSS_MISC_AHB_CLK 44
-#define MMSS_MISC_CXO_CLK 45
-#define MMSS_BIMC_SMMU_AHB_CLK 46
-#define MMSS_BIMC_SMMU_AXI_CLK 47
-#define MMSS_SNOC_DVM_AXI_CLK 48
-#define MMSS_THROTTLE_CAMSS_CXO_CLK 49
-#define MMSS_THROTTLE_CAMSS_AHB_CLK 50
-#define MMSS_THROTTLE_CAMSS_AXI_CLK 51
-#define MMSS_THROTTLE_MDSS_CXO_CLK 52
-#define MMSS_THROTTLE_MDSS_AHB_CLK 53
-#define MMSS_THROTTLE_MDSS_AXI_CLK 54
-#define MMSS_THROTTLE_VIDEO_CXO_CLK 55
-#define MMSS_THROTTLE_VIDEO_AHB_CLK 56
-#define MMSS_THROTTLE_VIDEO_AXI_CLK 57
-#define MMSS_VIDEO_CORE_CLK 58
-#define MMSS_VIDEO_AXI_CLK 59
-#define MMSS_VIDEO_AHB_CLK 60
-#define MMSS_MDSS_AHB_CLK 61
-#define MMSS_MDSS_HDMI_DP_AHB_CLK 62
-#define MMSS_MDSS_PCLK0_CLK 63
-#define MMSS_MDSS_PCLK1_CLK 64
-#define MMSS_MDSS_VSYNC_CLK 65
-#define MMSS_MDSS_BYTE0_CLK 66
-#define MMSS_MDSS_BYTE0_INTF_CLK 67
-#define MMSS_MDSS_BYTE1_CLK 68
-#define MMSS_MDSS_BYTE1_INTF_CLK 69
-#define MMSS_MDSS_ESC0_CLK 70
-#define MMSS_MDSS_ESC1_CLK 71
-#define MMSS_MDSS_DP_LINK_CLK 72
-#define MMSS_MDSS_DP_LINK_INTF_CLK 73
-#define MMSS_MDSS_DP_CRYPTO_CLK 74
-#define MMSS_MDSS_DP_PIXEL_CLK 75
-#define MMSS_MDSS_DP_AUX_CLK 76
-#define MMSS_MDSS_DP_GTC_CLK 77
-#define MMSS_CAMSS_TOP_AHB_CLK 78
-#define MMSS_CAMSS_AHB_CLK 79
-#define MMSS_CAMSS_GP0_CLK 80
-#define MMSS_CAMSS_GP1_CLK 81
-#define MMSS_CAMSS_MCLK0_CLK 82
-#define MMSS_CAMSS_MCLK1_CLK 83
-#define MMSS_CAMSS_MCLK2_CLK 84
-#define MMSS_CAMSS_MCLK3_CLK 85
-#define MMSS_CAMSS_CCI_CLK 86
-#define MMSS_CAMSS_CCI_AHB_CLK 87
-#define MMSS_CAMSS_CSI0PHYTIMER_CLK 88
-#define MMSS_CAMSS_CSI1PHYTIMER_CLK 89
-#define MMSS_CAMSS_CSI2PHYTIMER_CLK 90
-#define MMSS_CAMSS_JPEG_AHB_CLK 91
-#define MMSS_CAMSS_VFE_VBIF_AHB_CLK 92
-#define MMSS_CAMSS_VFE0_STREAM_CLK 93
-#define MMSS_CAMSS_VFE0_AHB_CLK 94
-#define MMSS_CAMSS_VFE1_STREAM_CLK 95
-#define MMSS_CAMSS_VFE1_AHB_CLK 96
-#define MMSS_CAMSS_CPP_VBIF_AHB_CLK 97
-#define MMSS_CAMSS_CPP_AHB_CLK 98
-#define MMSS_CAMSS_CSIPHY0_CLK 99
-#define MMSS_CAMSS_CSIPHY1_CLK 100
-#define MMSS_CAMSS_CSIPHY2_CLK 101
-#define MMSS_CSIPHY_AHB2CRIF_CLK 102
-#define MMSS_CAMSS_CSI0_CLK 103
-#define MMSS_CAMSS_CPHY_CSID0_CLK 104
-#define MMSS_CAMSS_CSI0_AHB_CLK 105
-#define MMSS_CAMSS_CSI0RDI_CLK 106
-#define MMSS_CAMSS_CSI0PIX_CLK 107
-#define MMSS_CAMSS_CSI1_CLK 108
-#define MMSS_CAMSS_CPHY_CSID1_CLK 109
-#define MMSS_CAMSS_CSI1_AHB_CLK 110
-#define MMSS_CAMSS_CSI1RDI_CLK 111
-#define MMSS_CAMSS_CSI1PIX_CLK 112
-#define MMSS_CAMSS_CSI2_CLK 113
-#define MMSS_CAMSS_CPHY_CSID2_CLK 114
-#define MMSS_CAMSS_CSI2_AHB_CLK 115
-#define MMSS_CAMSS_CSI2RDI_CLK 116
-#define MMSS_CAMSS_CSI2PIX_CLK 117
-#define MMSS_CAMSS_CSI3_CLK 118
-#define MMSS_CAMSS_CPHY_CSID3_CLK 119
-#define MMSS_CAMSS_CSI3_AHB_CLK 120
-#define MMSS_CAMSS_CSI3RDI_CLK 121
-#define MMSS_CAMSS_CSI3PIX_CLK 122
-#define MMSS_CAMSS_ISPIF_AHB_CLK 123
+#define AHB_CLK_SRC 0
+#define BYTE0_CLK_SRC 1
+#define BYTE1_CLK_SRC 2
+#define CAMSS_GP0_CLK_SRC 3
+#define CAMSS_GP1_CLK_SRC 4
+#define CCI_CLK_SRC 5
+#define CPP_CLK_SRC 6
+#define CSI0_CLK_SRC 7
+#define CSI0PHYTIMER_CLK_SRC 8
+#define CSI1_CLK_SRC 9
+#define CSI1PHYTIMER_CLK_SRC 10
+#define CSI2_CLK_SRC 11
+#define CSI2PHYTIMER_CLK_SRC 12
+#define CSI3_CLK_SRC 13
+#define CSIPHY_CLK_SRC 14
+#define DP_AUX_CLK_SRC 15
+#define DP_CRYPTO_CLK_SRC 16
+#define DP_GTC_CLK_SRC 17
+#define DP_LINK_CLK_SRC 18
+#define DP_PIXEL_CLK_SRC 19
+#define ESC0_CLK_SRC 20
+#define ESC1_CLK_SRC 21
+#define JPEG0_CLK_SRC 22
+#define MCLK0_CLK_SRC 23
+#define MCLK1_CLK_SRC 24
+#define MCLK2_CLK_SRC 25
+#define MCLK3_CLK_SRC 26
+#define MDP_CLK_SRC 27
+#define MMPLL0_PLL 28
+#define MMPLL0_PLL_OUT_AUX 29
+#define MMPLL0_PLL_OUT_AUX2 30
+#define MMPLL0_PLL_OUT_EARLY 31
+#define MMPLL0_PLL_OUT_MAIN 32
+#define MMPLL0_PLL_OUT_TEST 33
+#define MMPLL10_PLL 34
+#define MMPLL10_PLL_OUT_AUX 35
+#define MMPLL10_PLL_OUT_AUX2 36
+#define MMPLL10_PLL_OUT_EARLY 37
+#define MMPLL10_PLL_OUT_MAIN 38
+#define MMPLL10_PLL_OUT_TEST 39
+#define MMPLL1_PLL 40
+#define MMPLL1_PLL_OUT_AUX 41
+#define MMPLL1_PLL_OUT_AUX2 42
+#define MMPLL1_PLL_OUT_EARLY 43
+#define MMPLL1_PLL_OUT_MAIN 44
+#define MMPLL1_PLL_OUT_TEST 45
+#define MMPLL3_PLL 46
+#define MMPLL3_PLL_OUT_AUX 47
+#define MMPLL3_PLL_OUT_AUX2 48
+#define MMPLL3_PLL_OUT_EARLY 49
+#define MMPLL3_PLL_OUT_MAIN 50
+#define MMPLL3_PLL_OUT_TEST 51
+#define MMPLL4_PLL 52
+#define MMPLL4_PLL_OUT_AUX 53
+#define MMPLL4_PLL_OUT_AUX2 54
+#define MMPLL4_PLL_OUT_EARLY 55
+#define MMPLL4_PLL_OUT_MAIN 56
+#define MMPLL4_PLL_OUT_TEST 57
+#define MMPLL5_PLL 58
+#define MMPLL5_PLL_OUT_AUX 59
+#define MMPLL5_PLL_OUT_AUX2 60
+#define MMPLL5_PLL_OUT_EARLY 61
+#define MMPLL5_PLL_OUT_MAIN 62
+#define MMPLL5_PLL_OUT_TEST 63
+#define MMPLL6_PLL 64
+#define MMPLL6_PLL_OUT_AUX 65
+#define MMPLL6_PLL_OUT_AUX2 66
+#define MMPLL6_PLL_OUT_EARLY 67
+#define MMPLL6_PLL_OUT_MAIN 68
+#define MMPLL6_PLL_OUT_TEST 69
+#define MMPLL7_PLL 70
+#define MMPLL7_PLL_OUT_AUX 71
+#define MMPLL7_PLL_OUT_AUX2 72
+#define MMPLL7_PLL_OUT_EARLY 73
+#define MMPLL7_PLL_OUT_MAIN 74
+#define MMPLL7_PLL_OUT_TEST 75
+#define MMPLL8_PLL 76
+#define MMPLL8_PLL_OUT_AUX 77
+#define MMPLL8_PLL_OUT_AUX2 78
+#define MMPLL8_PLL_OUT_EARLY 79
+#define MMPLL8_PLL_OUT_MAIN 80
+#define MMPLL8_PLL_OUT_TEST 81
+#define MMSS_BIMC_SMMU_AHB_CLK 82
+#define MMSS_BIMC_SMMU_AXI_CLK 83
+#define MMSS_CAMSS_AHB_CLK 84
+#define MMSS_CAMSS_CCI_AHB_CLK 85
+#define MMSS_CAMSS_CCI_CLK 86
+#define MMSS_CAMSS_CPHY_CSID0_CLK 87
+#define MMSS_CAMSS_CPHY_CSID1_CLK 88
+#define MMSS_CAMSS_CPHY_CSID2_CLK 89
+#define MMSS_CAMSS_CPHY_CSID3_CLK 90
+#define MMSS_CAMSS_CPP_AHB_CLK 91
+#define MMSS_CAMSS_CPP_AXI_CLK 92
+#define MMSS_CAMSS_CPP_CLK 93
+#define MMSS_CAMSS_CPP_VBIF_AHB_CLK 94
+#define MMSS_CAMSS_CSI0_AHB_CLK 95
+#define MMSS_CAMSS_CSI0_CLK 96
+#define MMSS_CAMSS_CSI0PHYTIMER_CLK 97
+#define MMSS_CAMSS_CSI0PIX_CLK 98
+#define MMSS_CAMSS_CSI0RDI_CLK 99
+#define MMSS_CAMSS_CSI1_AHB_CLK 100
+#define MMSS_CAMSS_CSI1_CLK 101
+#define MMSS_CAMSS_CSI1PHYTIMER_CLK 102
+#define MMSS_CAMSS_CSI1PIX_CLK 103
+#define MMSS_CAMSS_CSI1RDI_CLK 104
+#define MMSS_CAMSS_CSI2_AHB_CLK 105
+#define MMSS_CAMSS_CSI2_CLK 106
+#define MMSS_CAMSS_CSI2PHYTIMER_CLK 107
+#define MMSS_CAMSS_CSI2PIX_CLK 108
+#define MMSS_CAMSS_CSI2RDI_CLK 109
+#define MMSS_CAMSS_CSI3_AHB_CLK 110
+#define MMSS_CAMSS_CSI3_CLK 111
+#define MMSS_CAMSS_CSI3PIX_CLK 112
+#define MMSS_CAMSS_CSI3RDI_CLK 113
+#define MMSS_CAMSS_CSI_VFE0_CLK 114
+#define MMSS_CAMSS_CSI_VFE1_CLK 115
+#define MMSS_CAMSS_CSIPHY0_CLK 116
+#define MMSS_CAMSS_CSIPHY1_CLK 117
+#define MMSS_CAMSS_CSIPHY2_CLK 118
+#define MMSS_CAMSS_GP0_CLK 119
+#define MMSS_CAMSS_GP1_CLK 120
+#define MMSS_CAMSS_ISPIF_AHB_CLK 121
+#define MMSS_CAMSS_JPEG0_CLK 122
+#define MMSS_CAMSS_JPEG_AHB_CLK 123
+#define MMSS_CAMSS_JPEG_AXI_CLK 124
+#define MMSS_CAMSS_MCLK0_CLK 125
+#define MMSS_CAMSS_MCLK1_CLK 126
+#define MMSS_CAMSS_MCLK2_CLK 127
+#define MMSS_CAMSS_MCLK3_CLK 128
+#define MMSS_CAMSS_MICRO_AHB_CLK 129
+#define MMSS_CAMSS_TOP_AHB_CLK 130
+#define MMSS_CAMSS_VFE0_AHB_CLK 131
+#define MMSS_CAMSS_VFE0_CLK 132
+#define MMSS_CAMSS_VFE0_STREAM_CLK 133
+#define MMSS_CAMSS_VFE1_AHB_CLK 134
+#define MMSS_CAMSS_VFE1_CLK 135
+#define MMSS_CAMSS_VFE1_STREAM_CLK 136
+#define MMSS_CAMSS_VFE_VBIF_AHB_CLK 137
+#define MMSS_CAMSS_VFE_VBIF_AXI_CLK 138
+#define MMSS_CSIPHY_AHB2CRIF_CLK 139
+#define MMSS_CXO_CLK 140
+#define MMSS_MDSS_AHB_CLK 141
+#define MMSS_MDSS_AXI_CLK 142
+#define MMSS_MDSS_BYTE0_CLK 143
+#define MMSS_MDSS_BYTE0_INTF_CLK 144
+#define MMSS_MDSS_BYTE1_CLK 145
+#define MMSS_MDSS_BYTE1_INTF_CLK 146
+#define MMSS_MDSS_DP_AUX_CLK 147
+#define MMSS_MDSS_DP_CRYPTO_CLK 148
+#define MMSS_MDSS_DP_GTC_CLK 149
+#define MMSS_MDSS_DP_LINK_CLK 150
+#define MMSS_MDSS_DP_LINK_INTF_CLK 151
+#define MMSS_MDSS_DP_PIXEL_CLK 152
+#define MMSS_MDSS_ESC0_CLK 153
+#define MMSS_MDSS_ESC1_CLK 154
+#define MMSS_MDSS_HDMI_DP_AHB_CLK 155
+#define MMSS_MDSS_MDP_CLK 156
+#define MMSS_MDSS_PCLK0_CLK 157
+#define MMSS_MDSS_PCLK1_CLK 158
+#define MMSS_MDSS_ROT_CLK 159
+#define MMSS_MDSS_VSYNC_CLK 160
+#define MMSS_MISC_AHB_CLK 161
+#define MMSS_MISC_CXO_CLK 162
+#define MMSS_MNOC_AHB_CLK 163
+#define MMSS_SNOC_DVM_AXI_CLK 164
+#define MMSS_THROTTLE_CAMSS_AHB_CLK 165
+#define MMSS_THROTTLE_CAMSS_AXI_CLK 166
+#define MMSS_THROTTLE_CAMSS_CXO_CLK 167
+#define MMSS_THROTTLE_MDSS_AHB_CLK 168
+#define MMSS_THROTTLE_MDSS_AXI_CLK 169
+#define MMSS_THROTTLE_MDSS_CXO_CLK 170
+#define MMSS_THROTTLE_VIDEO_AHB_CLK 171
+#define MMSS_THROTTLE_VIDEO_AXI_CLK 172
+#define MMSS_THROTTLE_VIDEO_CXO_CLK 173
+#define MMSS_VIDEO_AHB_CLK 174
+#define MMSS_VIDEO_AXI_CLK 175
+#define MMSS_VIDEO_CORE_CLK 176
+#define MMSS_VIDEO_SUBCORE0_CLK 177
+#define PCLK0_CLK_SRC 178
+#define PCLK1_CLK_SRC 179
+#define ROT_CLK_SRC 180
+#define VFE0_CLK_SRC 181
+#define VFE1_CLK_SRC 182
+#define VIDEO_CORE_CLK_SRC 183
+#define VSYNC_CLK_SRC 184
-/* Block Resets */
-#define MMSS_MNOCAHB_BCR 0
-#define MMSS_MISC_BCR 1
-#define MMSS_BTO_BCR 2
-#define MMSS_MNOCAXI_BCR 3
-#define MMSS_BIMC_SMMU_BCR 4
-#define MMSS_THROTTLE_CAMSS_BCR 5
-#define MMSS_THROTTLE_MDSS_BCR 6
-#define MMSS_THROTTLE_VIDEO_BCR 7
-#define MMSS_VIDEO_TOP_BCR 8
-#define MMSS_MDSS_BCR 9
-#define MMSS_CAMSS_TOP_BCR 10
-#define MMSS_CAMSS_AHB_BCR 11
-#define MMSS_CAMSS_MICRO_BCR 12
-#define MMSS_CAMSS_CCI_BCR 13
-#define MMSS_CAMSS_PHY0_BCR 14
-#define MMSS_CAMSS_PHY1_BCR 15
-#define MMSS_CAMSS_PHY2_BCR 16
-#define MMSS_CAMSS_JPEG_BCR 17
-#define MMSS_CAMSS_VFE_VBIF_BCR 18
-#define MMSS_CAMSS_VFE0_BCR 19
-#define MMSS_CAMSS_VFE1_BCR 20
-#define MMSS_CAMSS_CSI_VFE0_BCR 21
-#define MMSS_CAMSS_CSI_VFE1_BCR 22
-#define MMSS_CAMSS_CPP_TOP_BCR 23
-#define MMSS_CAMSS_CPP_BCR 24
-#define MMSS_CAMSS_CSIPHY_BCR 25
-#define MMSS_CAMSS_CSI0_BCR 26
-#define MMSS_CAMSS_CSI0RDI_BCR 27
-#define MMSS_CAMSS_CSI0PIX_BCR 28
-#define MMSS_CAMSS_CSI1_BCR 29
-#define MMSS_CAMSS_CSI1RDI_BCR 30
-#define MMSS_CAMSS_CSI1PIX_BCR 31
-#define MMSS_CAMSS_CSI2_BCR 32
-#define MMSS_CAMSS_CSI2RDI_BCR 33
-#define MMSS_CAMSS_CSI2PIX_BCR 34
-#define MMSS_CAMSS_CSI3_BCR 35
-#define MMSS_CAMSS_CSI3RDI_BCR 36
-#define MMSS_CAMSS_CSI3PIX_BCR 37
-#define MMSS_CAMSS_ISPIF_BCR 38
+#define BIMC_SMMU_GDSC 0
+#define CAMSS_CPP_GDSC 1
+#define CAMSS_TOP_GDSC 2
+#define CAMSS_VFE0_GDSC 3
+#define CAMSS_VFE1_GDSC 4
+#define MDSS_GDSC 5
+#define VIDEO_SUBCORE0_GDSC 6
+#define VIDEO_TOP_GDSC 7
-/* GDSC */
-#define VIDEO_TOP_GDSC 0
-#define VIDEO_SUBCORE0_GDSC 1
-#define CAMSS_VFE0_GDSC 2
-#define BIMC_SMMU_GDSC 3
-#define CAMSS_TOP_GDSC 4
-#define MDSS_GDSC 5
-#define CAMSS_CPP_GDSC 6
-#define CAMSS_VFE1_GDSC 7
#endif
diff --git a/include/linux/input/ft5x06_ts.h b/include/linux/input/ft5x06_ts.h
index a9577b62cb07..08ccbc9bd71c 100644
--- a/include/linux/input/ft5x06_ts.h
+++ b/include/linux/input/ft5x06_ts.h
@@ -3,7 +3,7 @@
* FocalTech ft5x06 TouchScreen driver header file.
*
* Copyright (c) 2010 Focal tech Ltd.
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -18,12 +18,28 @@
#ifndef __LINUX_FT5X06_TS_H__
#define __LINUX_FT5X06_TS_H__
+#define FT5X06_ID 0x55
+#define FT5X16_ID 0x0A
+#define FT5X36_ID 0x14
+#define FT6X06_ID 0x06
+
struct ft5x06_ts_platform_data {
- unsigned long irqflags;
- u32 x_max;
- u32 y_max;
+ u32 irqflags;
u32 irq_gpio;
+ u32 irq_gpio_flags;
u32 reset_gpio;
+ u32 reset_gpio_flags;
+ u32 family_id;
+ u32 x_max;
+ u32 y_max;
+ u32 x_min;
+ u32 y_min;
+ u32 panel_minx;
+ u32 panel_miny;
+ u32 panel_maxx;
+ u32 panel_maxy;
+ bool no_force_update;
+ bool i2c_pull_up;
int (*power_init)(bool);
int (*power_on)(bool);
};
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 7d1e374e176c..56e78254286e 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -174,9 +174,9 @@ enum power_supply_property {
/* Local extensions */
POWER_SUPPLY_PROP_USB_HC,
POWER_SUPPLY_PROP_USB_OTG,
- POWER_SUPPLY_PROP_CHARGE_ENABLED,
POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED,
POWER_SUPPLY_PROP_CHARGING_ENABLED,
+ POWER_SUPPLY_PROP_PIN_ENABLED,
POWER_SUPPLY_PROP_INPUT_SUSPEND,
POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 8d9016e3557c..3464726c408a 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -2738,6 +2738,333 @@ struct afe_param_id_set_topology_cfg {
u32 topology_id;
} __packed;
+
+/*
+ * Generic encoder module ID.
+ * This module supports the following parameter IDs:
+ * #AVS_ENCODER_PARAM_ID_ENC_FMT_ID (cannot be set run time)
+ * #AVS_ENCODER_PARAM_ID_ENC_CFG_BLK (may be set run time)
+ * #AVS_ENCODER_PARAM_ID_ENC_BITRATE (may be set run time)
+ * #AVS_ENCODER_PARAM_ID_PACKETIZER_ID (cannot be set run time)
+ * Opcode - AVS_MODULE_ID_ENCODER
+ * AFE Command AFE_PORT_CMD_SET_PARAM_V2 supports this module ID.
+ */
+#define AFE_MODULE_ID_ENCODER 0x00013229
+
+/* Macro for defining the packetizer ID: COP. */
+#define AFE_MODULE_ID_PACKETIZER_COP 0x0001322A
+
+/*
+ * Packetizer type parameter for the #AVS_MODULE_ID_ENCODER module.
+ * This parameter cannot be set runtime.
+ */
+#define AFE_ENCODER_PARAM_ID_PACKETIZER_ID 0x0001322E
+
+/*
+ * Encoder config block parameter for the #AVS_MODULE_ID_ENCODER module.
+ * This parameter may be set runtime.
+ */
+#define AFE_ENCODER_PARAM_ID_ENC_CFG_BLK 0x0001322C
+
+/*
+ * Encoder format ID parameter for the #AVS_MODULE_ID_ENCODER module.
+ * This parameter cannot be set runtime.
+ */
+#define AFE_ENCODER_PARAM_ID_ENC_FMT_ID 0x0001322B
+
+/*
+ * Data format to send compressed data
+ * is transmitted/received over Slimbus lines.
+ */
+#define AFE_SB_DATA_FORMAT_GENERIC_COMPRESSED 0x3
+
+/*
+ * ID for AFE port module. This will be used to define port properties.
+ * This module supports following parameter IDs:
+ * #AFE_PARAM_ID_PORT_MEDIA_TYPE
+ * To configure the port property, the client must use the
+ * #AFE_PORT_CMD_SET_PARAM_V2 command,
+ * and fill the module ID with the respective parameter IDs as listed above.
+ * @apr_hdr_fields
+ * Opcode -- AFE_MODULE_PORT
+ */
+#define AFE_MODULE_PORT 0x000102a6
+
+/*
+ * ID of the parameter used by #AFE_MODULE_PORT to set the port media type.
+ * parameter ID is currently supported using#AFE_PORT_CMD_SET_PARAM_V2 command.
+ */
+#define AFE_PARAM_ID_PORT_MEDIA_TYPE 0x000102a7
+
+/*
+ * Macros for defining the "data_format" field in the
+ * #AFE_PARAM_ID_PORT_MEDIA_TYPE
+ */
+#define AFE_PORT_DATA_FORMAT_PCM 0x0
+#define AFE_PORT_DATA_FORMAT_GENERIC_COMPRESSED 0x1
+
+/*
+ * Macro for defining the "minor_version" field in the
+ * #AFE_PARAM_ID_PORT_MEDIA_TYPE
+ */
+#define AFE_API_VERSION_PORT_MEDIA_TYPE 0x1
+
+#define ASM_MEDIA_FMT_NONE 0x0
+
+/*
+ * Media format ID for SBC encode configuration.
+ * @par SBC encode configuration (asm_sbc_enc_cfg_t)
+ * @table{weak__asm__sbc__enc__cfg__t}
+ */
+#define ASM_MEDIA_FMT_SBC 0x00010BF2
+
+/* SBC channel Mono mode.*/
+#define ASM_MEDIA_FMT_SBC_CHANNEL_MODE_MONO 1
+
+/* SBC channel Stereo mode. */
+#define ASM_MEDIA_FMT_SBC_CHANNEL_MODE_STEREO 2
+
+/* SBC channel Dual Mono mode. */
+#define ASM_MEDIA_FMT_SBC_CHANNEL_MODE_DUAL_MONO 8
+
+/* SBC channel Joint Stereo mode. */
+#define ASM_MEDIA_FMT_SBC_CHANNEL_MODE_JOINT_STEREO 9
+
+/* SBC bit allocation method = loudness. */
+#define ASM_MEDIA_FMT_SBC_ALLOCATION_METHOD_LOUDNESS 0
+
+/* SBC bit allocation method = SNR. */
+#define ASM_MEDIA_FMT_SBC_ALLOCATION_METHOD_SNR 1
+
+
+/*
+ * Payload of the SBC encoder configuration parameters in the
+ * #ASM_MEDIA_FMT_SBC media format.
+ */
+struct asm_sbc_enc_cfg_t {
+ /*
+ * Number of subbands.
+ * @values 4, 8
+ */
+ uint32_t num_subbands;
+
+ /*
+ * Size of the encoded block in samples.
+ * @values 4, 8, 12, 16
+ */
+ uint32_t blk_len;
+
+ /*
+ * Mode used to allocate bits between channels.
+ * @values
+ * 0 (Native mode)
+ * #ASM_MEDIA_FMT_SBC_CHANNEL_MODE_MONO
+ * #ASM_MEDIA_FMT_SBC_CHANNEL_MODE_STEREO
+ * #ASM_MEDIA_FMT_SBC_CHANNEL_MODE_DUAL_MONO
+ * #ASM_MEDIA_FMT_SBC_CHANNEL_MODE_JOINT_STEREO
+ * Native mode indicates that encoding must be performed with the number
+ * of channels at the input.
+ * If postprocessing outputs one-channel data, Mono mode is used. If
+ * postprocessing outputs two-channel data, Stereo mode is used.
+ * The number of channels must not change during encoding.
+ */
+ uint32_t channel_mode;
+
+ /*
+ * Encoder bit allocation method.
+ * @values
+ * #ASM_MEDIA_FMT_SBC_ALLOCATION_METHOD_LOUDNESS
+ * #ASM_MEDIA_FMT_SBC_ALLOCATION_METHOD_SNR @tablebulletend
+ */
+ uint32_t alloc_method;
+
+ /*
+ * Number of encoded bits per second.
+ * @values
+ * Mono channel -- Maximum of 320 kbps
+ * Stereo channel -- Maximum of 512 kbps @tablebulletend
+ */
+ uint32_t bit_rate;
+
+ /*
+ * Number of samples per second.
+ * @values 0 (Native mode), 16000, 32000, 44100, 48000&nbsp;Hz
+ * Native mode indicates that encoding must be performed with the
+ * sampling rate at the input.
+ * The sampling rate must not change during encoding.
+ */
+ uint32_t sample_rate;
+};
+
+#define ASM_MEDIA_FMT_AAC_AOT_LC 2
+#define ASM_MEDIA_FMT_AAC_AOT_SBR 5
+#define ASM_MEDIA_FMT_AAC_AOT_PS 29
+#define ASM_MEDIA_FMT_AAC_FORMAT_FLAG_ADTS 0
+#define ASM_MEDIA_FMT_AAC_FORMAT_FLAG_RAW 3
+
+struct asm_aac_enc_cfg_v2_t {
+
+ /* Encoding rate in bits per second.*/
+ uint32_t bit_rate;
+
+ /*
+ * Encoding mode.
+ * Supported values:
+ * #ASM_MEDIA_FMT_AAC_AOT_LC
+ * #ASM_MEDIA_FMT_AAC_AOT_SBR
+ * #ASM_MEDIA_FMT_AAC_AOT_PS
+ */
+ uint32_t enc_mode;
+
+ /*
+ * AAC format flag.
+ * Supported values:
+ * #ASM_MEDIA_FMT_AAC_FORMAT_FLAG_ADTS
+ * #ASM_MEDIA_FMT_AAC_FORMAT_FLAG_RAW
+ */
+ uint16_t aac_fmt_flag;
+
+ /*
+ * Number of channels to encode.
+ * Supported values:
+ * 0 - Native mode
+ * 1 - Mono
+ * 2 - Stereo
+ * Other values are not supported.
+ * @note1hang The eAAC+ encoder mode supports only stereo.
+ * Native mode indicates that encoding must be performed with the
+ * number of channels at the input.
+ * The number of channels must not change during encoding.
+ */
+ uint32_t channel_cfg;
+
+ /*
+ * Number of samples per second.
+ * Supported values: - 0 -- Native mode - For other values,
+ * Native mode indicates that encoding must be performed with the
+ * sampling rate at the input.
+ * The sampling rate must not change during encoding.
+ */
+ uint32_t sample_rate;
+} __packed;
+
+/* FMT ID for apt-X Classic */
+#define ASM_MEDIA_FMT_APTX 0x000131ff
+
+/* FMT ID for apt-X HD */
+#define ASM_MEDIA_FMT_APTX_HD 0x00013200
+
+#define PCM_CHANNEL_L 1
+#define PCM_CHANNEL_R 2
+#define PCM_CHANNEL_C 3
+
+struct asm_custom_enc_cfg_aptx_t {
+ uint32_t sample_rate;
+ /* Mono or stereo */
+ uint16_t num_channels;
+ uint16_t reserved;
+ /* num_ch == 1, then PCM_CHANNEL_C,
+ * num_ch == 2, then {PCM_CHANNEL_L, PCM_CHANNEL_R}
+ */
+ uint8_t channel_mapping[8];
+ uint32_t custom_size;
+} __packed;
+
+struct afe_enc_fmt_id_param_t {
+ /*
+ * Supported values:
+ * #ASM_MEDIA_FMT_SBC
+ * #ASM_MEDIA_FMT_AAC_V2
+ * Any OpenDSP supported values
+ */
+ uint32_t fmt_id;
+} __packed;
+
+struct afe_port_media_type_t {
+ /*
+ * Minor version
+ * @values #AFE_API_VERSION_PORT_MEDIA_TYPE.
+ */
+ uint32_t minor_version;
+
+ /*
+ * Sampling rate of the port.
+ * @values
+ * #AFE_PORT_SAMPLE_RATE_8K
+ * #AFE_PORT_SAMPLE_RATE_11_025K
+ * #AFE_PORT_SAMPLE_RATE_12K
+ * #AFE_PORT_SAMPLE_RATE_16K
+ * #AFE_PORT_SAMPLE_RATE_22_05K
+ * #AFE_PORT_SAMPLE_RATE_24K
+ * #AFE_PORT_SAMPLE_RATE_32K
+ * #AFE_PORT_SAMPLE_RATE_44_1K
+ * #AFE_PORT_SAMPLE_RATE_48K
+ * #AFE_PORT_SAMPLE_RATE_88_2K
+ * #AFE_PORT_SAMPLE_RATE_96K
+ * #AFE_PORT_SAMPLE_RATE_176_4K
+ * #AFE_PORT_SAMPLE_RATE_192K
+ * #AFE_PORT_SAMPLE_RATE_352_8K
+ * #AFE_PORT_SAMPLE_RATE_384K
+ */
+ uint32_t sample_rate;
+
+ /*
+ * Bit width of the sample.
+ * @values 16, 24
+ */
+ uint16_t bit_width;
+
+ /*
+ * Number of channels.
+ * @values 1 to #AFE_PORT_MAX_AUDIO_CHAN_CNT
+ */
+ uint16_t num_channels;
+
+ /*
+ * Data format supported by this port.
+ * If the port media type and device media type are different,
+ * it signifies a encoding/decoding use case
+ * @values
+ * #AFE_PORT_DATA_FORMAT_PCM
+ * #AFE_PORT_DATA_FORMAT_GENERIC_COMPRESSED
+ */
+ uint16_t data_format;
+
+ /*This field must be set to zero.*/
+ uint16_t reserved;
+} __packed;
+
+union afe_enc_config_data {
+ struct asm_sbc_enc_cfg_t sbc_config;
+ struct asm_aac_enc_cfg_v2_t aac_config;
+ struct asm_custom_enc_cfg_aptx_t aptx_config;
+};
+
+struct afe_enc_config {
+ u32 format;
+ union afe_enc_config_data data;
+};
+
+struct afe_enc_cfg_blk_param_t {
+ uint32_t enc_cfg_blk_size;
+ /*
+ *Size of the encoder configuration block that follows this member
+ */
+ union afe_enc_config_data enc_blk_config;
+};
+
+/*
+ * Payload of the AVS_ENCODER_PARAM_ID_PACKETIZER_ID parameter.
+ */
+struct avs_enc_packetizer_id_param_t {
+ /*
+ * Supported values:
+ * #AVS_MODULE_ID_PACKETIZER_COP
+ * Any OpenDSP supported values
+ */
+ uint32_t enc_packetizer_id;
+};
+
union afe_port_config {
struct afe_param_id_pcm_cfg pcm;
struct afe_param_id_i2s_cfg i2s;
@@ -2751,6 +3078,10 @@ union afe_port_config {
struct afe_param_id_set_topology_cfg topology;
struct afe_param_id_tdm_cfg tdm;
struct afe_param_id_usb_audio_cfg usb_audio;
+ struct afe_enc_fmt_id_param_t enc_fmt;
+ struct afe_port_media_type_t media_type;
+ struct afe_enc_cfg_blk_param_t enc_blk_param;
+ struct avs_enc_packetizer_id_param_t enc_pkt_id_param;
} __packed;
struct afe_audioif_config_command_no_payload {
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 5cd65357dd95..6be903a4c8d0 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -274,6 +274,9 @@ int afe_rt_proxy_port_read(phys_addr_t buf_addr_p,
void afe_set_cal_mode(u16 port_id, enum afe_cal_mode afe_cal_mode);
int afe_port_start(u16 port_id, union afe_port_config *afe_config,
u32 rate);
+int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config,
+ u32 rate, u16 afe_in_channels,
+ struct afe_enc_config *enc_config);
int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
int l_ch, int r_ch, u32 enable);
int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib);
diff --git a/include/uapi/linux/mfd/wcd9xxx/Kbuild b/include/uapi/linux/mfd/wcd9xxx/Kbuild
index da9fe03b0bed..8e55965bbe7e 100755
--- a/include/uapi/linux/mfd/wcd9xxx/Kbuild
+++ b/include/uapi/linux/mfd/wcd9xxx/Kbuild
@@ -1 +1,2 @@
+header-y += wcd9xxx_registers.h
header-y += wcd9320_registers.h
diff --git a/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h b/include/uapi/linux/mfd/wcd9xxx/wcd9xxx_registers.h
index 1dac14bd8427..a9fe10d8cd6e 100755..100644
--- a/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
+++ b/include/uapi/linux/mfd/wcd9xxx/wcd9xxx_registers.h
@@ -330,6 +330,8 @@
#define WCD9XXX_A_ANA_HPH (0x609)
#define WCD9XXX_A_CDC_CLSH_CRC (0xC01)
#define WCD9XXX_FLYBACK_EN (0x6A4)
+#define WCD9XXX_FLYBACK_VNEG_CTRL_1 (0x6A5)
+#define WCD9XXX_FLYBACK_VNEGDAC_CTRL_2 (0x6AF)
#define WCD9XXX_RX_BIAS_FLYB_BUFF (0x6C7)
#define WCD9XXX_HPH_L_EN (0x6D3)
#define WCD9XXX_HPH_R_EN (0x6D6)
@@ -341,4 +343,13 @@
#define WCD9XXX_CDC_RX2_RX_PATH_CTL (0xB69)
#define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_CONTROL (0xD41)
#define WCD9XXX_CLASSH_CTRL_CCL_1 (0x69C)
+
+/* RX Gain control registers of codecs from and above WCD9335 */
+#define WCD9XXX_CDC_RX1_RX_VOL_CTL (0xB59)
+#define WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL (0xB5C)
+#define WCD9XXX_CDC_RX1_RX_PATH_SEC1 (0xB5E)
+#define WCD9XXX_CDC_RX2_RX_VOL_CTL (0xB6D)
+#define WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL (0xB70)
+#define WCD9XXX_CDC_RX2_RX_PATH_SEC1 (0xB72)
+
#endif
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 37731292f8a1..1cfd381642da 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -365,21 +365,6 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
goto out_release;
}
- /*
- * By now we've cleared cpu_active_mask, wait for all preempt-disabled
- * and RCU users of this state to go away such that all new such users
- * will observe it.
- *
- * For CONFIG_PREEMPT we have preemptible RCU and its sync_rcu() might
- * not imply sync_sched(), so wait for both.
- *
- * Do sync before park smpboot threads to take care the rcu boost case.
- */
- if (IS_ENABLED(CONFIG_PREEMPT))
- synchronize_rcu_mult(call_rcu, call_rcu_sched);
- else
- synchronize_rcu();
-
smpboot_park_threads(cpu);
/*
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 2ade632197d5..2df78d45a096 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -2075,12 +2075,30 @@ static void cpuset_bind(struct cgroup_subsys_state *root_css)
mutex_unlock(&cpuset_mutex);
}
+static int cpuset_allow_attach(struct cgroup_taskset *tset)
+{
+ const struct cred *cred = current_cred(), *tcred;
+ struct task_struct *task;
+ struct cgroup_subsys_state *css;
+
+ cgroup_taskset_for_each(task, css, tset) {
+ tcred = __task_cred(task);
+
+ if ((current != task) && !capable(CAP_SYS_ADMIN) &&
+ cred->euid.val != tcred->uid.val && cred->euid.val != tcred->suid.val)
+ return -EACCES;
+ }
+
+ return 0;
+}
+
struct cgroup_subsys cpuset_cgrp_subsys = {
.css_alloc = cpuset_css_alloc,
.css_online = cpuset_css_online,
.css_offline = cpuset_css_offline,
.css_free = cpuset_css_free,
.can_attach = cpuset_can_attach,
+ .allow_attach = cpuset_allow_attach,
.cancel_attach = cpuset_cancel_attach,
.attach = cpuset_attach,
.bind = cpuset_bind,
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index bc0e504f33a6..80649934cf3b 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -993,7 +993,7 @@ static struct genl_multicast_group genl_ctrl_groups[] = {
static int genl_bind(struct net *net, int group)
{
- int i, err = -ENOENT;
+ int i, err = 0;
down_read(&cb_lock);
for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index 1626d1553986..8e1aff46ac23 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -375,13 +375,13 @@ country DK: DFS-ETSI
country DM: DFS-FCC
(2402 - 2472 @ 40), (30)
- (5170 - 5250 @ 80), (17), AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5735 - 5835 @ 80), (30)
country DO: DFS-FCC
(2402 - 2472 @ 40), (30)
- (5170 - 5250 @ 80), (17), AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5735 - 5835 @ 80), (30)
@@ -417,8 +417,8 @@ country EE: DFS-ETSI
country EG: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 20), (20)
- (5250 - 5330 @ 20), (20), DFS
+ (5170 - 5250 @ 20), (23)
+ (5250 - 5330 @ 20), (23), DFS
country ES: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -654,14 +654,14 @@ country IE: DFS-ETSI
country IL: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
country IN: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
- (5735 - 5835 @ 80), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (30)
country IR:
(2402 - 2482 @ 40), (20)
@@ -737,8 +737,8 @@ country KH: DFS-ETSI
country KN: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5490 - 5710 @ 160), (30), DFS
(5735 - 5815 @ 80), (30)
@@ -758,8 +758,8 @@ country KP: DFS-ETSI
country KW: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
country KY: DFS-FCC
(2402 - 2482 @ 40), (20)
@@ -781,7 +781,7 @@ country LB: DFS-FCC
country LC: DFS-ETSI
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5250 - 5330 @ 80), (30), DFS, AUTO-BW
(5490 - 5710 @ 160), (30), DFS
(5735 - 5815 @ 80), (30)
@@ -866,8 +866,8 @@ country LV: DFS-ETSI
country MA: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
country MC: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -984,19 +984,19 @@ country MX: DFS-FCC
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-country NA: DFS-ETSI
- (2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5735 - 5815 @ 80), (30)
-
country MY: DFS-FCC
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (24), AUTO-BW
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5650 @ 160), (24), DFS
- (5735 - 5835 @ 80), (24)
+ (5735 - 5815 @ 80), (24)
+
+country NA: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ (5735 - 5835 @ 80), (33)
country NG: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -1065,7 +1065,7 @@ country OM: DFS-ETSI
country PA: DFS-FCC
(2402 - 2472 @ 40), (30)
- (5170 - 5250 @ 80), (17), AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5735 - 5835 @ 80), (30)
@@ -1207,8 +1207,8 @@ country RS: DFS-ETSI
country RU: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5490 - 5730 @ 160), (30), DFS
(5735 - 5835 @ 80), (30)
@@ -1298,7 +1298,7 @@ country SR: DFS-ETSI
country SV: DFS-FCC
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 20), (17)
+ (5170 - 5250 @ 20), (23)
(5250 - 5330 @ 20), (23), DFS
(5735 - 5835 @ 20), (30)
@@ -1333,8 +1333,8 @@ country TH: DFS-FCC
country TN: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
country TR: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -1416,7 +1416,7 @@ country UY: DFS-FCC
country UZ: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (20), DFS, AUTO-BW
country VC: DFS-ETSI
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 6fc326421108..dc6e95b977c9 100755
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -739,9 +739,6 @@ config SND_SOC_WSA881X_ANALOG
tristate
select REGMAP_I2C
-config SND_SOC_MSM8X16_WCD
- tristate
-
config SND_SOC_WCD9XXX
tristate
default y if SND_SOC_WCD9320=y || SND_SOC_WCD9330=y || SND_SOC_WCD9335=y
@@ -984,4 +981,7 @@ config SND_SOC_MSM_HDMI_CODEC_RX
help
HDMI audio drivers should be built only if the platform
supports hdmi panel.
+
+source "sound/soc/codecs/msm8x16/Kconfig"
+
endmenu
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 4b79b277ce29..f237a2188fe1 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -140,7 +140,6 @@ audio-ext-clock-objs := audio-ext-clk.o
snd-soc-wcd-cpe-objs := wcd_cpe_services.o wcd_cpe_core.o
snd-soc-wsa881x-objs := wsa881x.o wsa881x-tables.o wsa881x-regmap.o wsa881x-temp-sensor.o
snd-soc-wcd-mbhc-objs := wcd-mbhc-v2.o
-snd-soc-msm8952-wcd-objs := msm8x16-wcd.o msm8x16-wcd-tables.o
snd-soc-wsa881x-analog-objs := wsa881x-analog.o wsa881x-tables-analog.o
snd-soc-wsa881x-analog-objs += wsa881x-regmap-analog.o wsa881x-irq.o
snd-soc-wcd-dsp-utils-objs := wcd-dsp-utils.o
@@ -348,7 +347,6 @@ obj-$(CONFIG_SND_SOC_WCD934X) += wcd934x/
obj-$(CONFIG_AUDIO_EXT_CLK) += audio-ext-clock.o
obj-$(CONFIG_SND_SOC_WCD9XXX) += snd-soc-wcd9xxx.o
obj-$(CONFIG_SND_SOC_WCD9XXX_V2) += snd-soc-wcd9xxx-v2.o
-obj-$(CONFIG_SND_SOC_MSM8X16_WCD) += snd-soc-msm8952-wcd.o msm8916-wcd-irq.o
obj-$(CONFIG_SND_SOC_WCD_CPE) += snd-soc-wcd-cpe.o
obj-$(CONFIG_SND_SOC_WCD_MBHC) += snd-soc-wcd-mbhc.o
obj-$(CONFIG_SND_SOC_WSA881X) += snd-soc-wsa881x.o
@@ -416,3 +414,4 @@ obj-$(CONFIG_SND_SOC_MSM_STUB) += snd-soc-msm-stub.o
# Amp
obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o
+obj-y += msm8x16/
diff --git a/sound/soc/codecs/msm8x16/Kconfig b/sound/soc/codecs/msm8x16/Kconfig
new file mode 100644
index 000000000000..d225b7a56925
--- /dev/null
+++ b/sound/soc/codecs/msm8x16/Kconfig
@@ -0,0 +1,3 @@
+
+config SND_SOC_MSM8X16_WCD
+ tristate "MSM Internal PMIC based codec"
diff --git a/sound/soc/codecs/msm8x16/Makefile b/sound/soc/codecs/msm8x16/Makefile
new file mode 100644
index 000000000000..36a3d046a307
--- /dev/null
+++ b/sound/soc/codecs/msm8x16/Makefile
@@ -0,0 +1,3 @@
+snd-soc-msm8952-wcd-objs := msm8x16-wcd.o msm8x16-wcd-tables.o msm89xx-regmap.o
+obj-$(CONFIG_SND_SOC_MSM8X16_WCD) += snd-soc-msm8952-wcd.o msm8916-wcd-irq.o
+
diff --git a/sound/soc/codecs/msm8916-wcd-irq.c b/sound/soc/codecs/msm8x16/msm8916-wcd-irq.c
index 8fbd72964108..a722842b106b 100644
--- a/sound/soc/codecs/msm8916-wcd-irq.c
+++ b/sound/soc/codecs/msm8x16/msm8916-wcd-irq.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -56,20 +56,20 @@ char *irq_names[MAX_NUM_IRQS] = {
};
int order[MAX_NUM_IRQS] = {
- MSM8X16_WCD_IRQ_SPKR_CNP,
- MSM8X16_WCD_IRQ_SPKR_CLIP,
- MSM8X16_WCD_IRQ_SPKR_OCP,
- MSM8X16_WCD_IRQ_MBHC_INSREM_DET1,
- MSM8X16_WCD_IRQ_MBHC_RELEASE,
- MSM8X16_WCD_IRQ_MBHC_PRESS,
- MSM8X16_WCD_IRQ_MBHC_INSREM_DET,
- MSM8X16_WCD_IRQ_MBHC_HS_DET,
- MSM8X16_WCD_IRQ_EAR_OCP,
- MSM8X16_WCD_IRQ_HPHR_OCP,
- MSM8X16_WCD_IRQ_HPHL_OCP,
- MSM8X16_WCD_IRQ_EAR_CNP,
- MSM8X16_WCD_IRQ_HPHR_CNP,
- MSM8X16_WCD_IRQ_HPHL_CNP,
+ MSM89XX_IRQ_SPKR_CNP,
+ MSM89XX_IRQ_SPKR_CLIP,
+ MSM89XX_IRQ_SPKR_OCP,
+ MSM89XX_IRQ_MBHC_INSREM_DET1,
+ MSM89XX_IRQ_MBHC_RELEASE,
+ MSM89XX_IRQ_MBHC_PRESS,
+ MSM89XX_IRQ_MBHC_INSREM_DET,
+ MSM89XX_IRQ_MBHC_HS_DET,
+ MSM89XX_IRQ_EAR_OCP,
+ MSM89XX_IRQ_HPHR_OCP,
+ MSM89XX_IRQ_HPHL_OCP,
+ MSM89XX_IRQ_EAR_CNP,
+ MSM89XX_IRQ_HPHR_CNP,
+ MSM89XX_IRQ_HPHL_CNP,
};
enum wcd9xxx_spmi_pm_state {
@@ -101,18 +101,18 @@ void wcd9xxx_spmi_enable_irq(int irq)
pr_debug("%s: irqno =%d\n", __func__, irq);
if ((irq >= 0) && (irq <= 7)) {
snd_soc_update_bits(map.codec,
- MSM8X16_WCD_A_DIGITAL_INT_EN_CLR,
+ MSM89XX_PMIC_DIGITAL_INT_EN_CLR,
(0x01 << irq), 0x00);
snd_soc_update_bits(map.codec,
- MSM8X16_WCD_A_DIGITAL_INT_EN_SET,
+ MSM89XX_PMIC_DIGITAL_INT_EN_SET,
(0x01 << irq), (0x01 << irq));
}
if ((irq > 7) && (irq <= 15)) {
snd_soc_update_bits(map.codec,
- MSM8X16_WCD_A_ANALOG_INT_EN_CLR,
+ MSM89XX_PMIC_ANALOG_INT_EN_CLR,
(0x01 << (irq - 8)), 0x00);
snd_soc_update_bits(map.codec,
- MSM8X16_WCD_A_ANALOG_INT_EN_SET,
+ MSM89XX_PMIC_ANALOG_INT_EN_SET,
(0x01 << (irq - 8)), (0x01 << (irq - 8)));
}
@@ -130,19 +130,19 @@ void wcd9xxx_spmi_disable_irq(int irq)
pr_debug("%s: irqno =%d\n", __func__, irq);
if ((irq >= 0) && (irq <= 7)) {
snd_soc_update_bits(map.codec,
- MSM8X16_WCD_A_DIGITAL_INT_EN_SET,
+ MSM89XX_PMIC_DIGITAL_INT_EN_SET,
(0x01 << (irq)), 0x00);
snd_soc_update_bits(map.codec,
- MSM8X16_WCD_A_DIGITAL_INT_EN_CLR,
+ MSM89XX_PMIC_DIGITAL_INT_EN_CLR,
(0x01 << irq), (0x01 << irq));
}
if ((irq > 7) && (irq <= 15)) {
snd_soc_update_bits(map.codec,
- MSM8X16_WCD_A_ANALOG_INT_EN_SET,
+ MSM89XX_PMIC_ANALOG_INT_EN_SET,
(0x01 << (irq - 8)), 0x00);
snd_soc_update_bits(map.codec,
- MSM8X16_WCD_A_ANALOG_INT_EN_CLR,
+ MSM89XX_PMIC_ANALOG_INT_EN_CLR,
(0x01 << (irq - 8)), (0x01 << (irq - 8)));
}
@@ -161,10 +161,6 @@ int wcd9xxx_spmi_request_irq(int irq, irq_handler_t handler,
int rc;
unsigned long irq_flags;
- map.linuxirq[irq] =
- spmi_get_irq_byname(map.spmi[BIT_BYTE(irq)], NULL,
- irq_names[irq]);
-
if (strcmp(name, "mbhc sw intr"))
irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
IRQF_ONESHOT;
@@ -234,7 +230,7 @@ static irqreturn_t wcd9xxx_spmi_irq_handler(int linux_irq, void *data)
for (i = 0; i < NUM_IRQ_REGS; i++) {
status[i] |= snd_soc_read(map.codec,
BIT_BYTE(irq) * 0x100 +
- MSM8X16_WCD_A_DIGITAL_INT_LATCHED_STS);
+ MSM89XX_PMIC_DIGITAL_INT_LATCHED_STS);
status[i] &= ~map.mask[i];
}
for (i = 0; i < MAX_NUM_IRQS; i++) {
@@ -418,10 +414,10 @@ void wcd9xxx_spmi_set_codec(struct snd_soc_codec *codec)
map.codec = codec;
}
-void wcd9xxx_spmi_set_dev(struct platform_device *pdev, int i)
+void wcd9xxx_spmi_set_dev(struct spmi_device *spmi, int i)
{
if (i < NUM_IRQ_REGS)
- map.spmi[i] = pdev;
+ map.spmi[i] = spmi;
}
int wcd9xxx_spmi_irq_init(void)
diff --git a/sound/soc/codecs/msm8916-wcd-irq.h b/sound/soc/codecs/msm8x16/msm8916-wcd-irq.h
index 659e52cc2a5e..659e52cc2a5e 100644
--- a/sound/soc/codecs/msm8916-wcd-irq.h
+++ b/sound/soc/codecs/msm8x16/msm8916-wcd-irq.h
diff --git a/sound/soc/codecs/msm8x16/msm89xx-regmap.c b/sound/soc/codecs/msm8x16/msm89xx-regmap.c
new file mode 100644
index 000000000000..007b74c8b867
--- /dev/null
+++ b/sound/soc/codecs/msm8x16/msm89xx-regmap.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include "msm8x16-wcd.h"
+
+/*
+ * Default register reset values that are common across different versions
+ * are defined here. If a register reset value is changed based on version
+ * then remove it from this structure and add it in version specific
+ * structures.
+ */
+static struct reg_default
+ msm89xx_cdc_core_defaults[MSM89XX_CDC_CORE_CACHE_SIZE] = {
+ {MSM89XX_CDC_CORE_CLK_RX_RESET_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_TX_RESET_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_DMIC_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_RX_I2S_CTL, 0x13},
+ {MSM89XX_CDC_CORE_CLK_TX_I2S_CTL, 0x13},
+ {MSM89XX_CDC_CORE_CLK_OTHR_RESET_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_OTHR_CTL, 0x04},
+ {MSM89XX_CDC_CORE_CLK_RX_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_MCLK_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_PDM_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_SD_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_WSA_VI_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CLK_RX_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX1_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX2_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX3_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX1_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX2_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX3_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX1_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX2_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX3_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX1_B4_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX2_B4_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX3_B4_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX1_B5_CTL, 0x68},
+ {MSM89XX_CDC_CORE_RX2_B5_CTL, 0x68},
+ {MSM89XX_CDC_CORE_RX3_B5_CTL, 0x68},
+ {MSM89XX_CDC_CORE_RX1_B6_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX2_B6_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX3_B6_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX1_VOL_CTL_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX2_VOL_CTL_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX3_VOL_CTL_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX1_VOL_CTL_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX2_VOL_CTL_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_RX3_VOL_CTL_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TOP_GAIN_UPDATE, 0x00},
+ {MSM89XX_CDC_CORE_TOP_CTL, 0x01},
+ {MSM89XX_CDC_CORE_COMP0_B1_CTL, 0x30},
+ {MSM89XX_CDC_CORE_COMP0_B2_CTL, 0xB5},
+ {MSM89XX_CDC_CORE_COMP0_B3_CTL, 0x28},
+ {MSM89XX_CDC_CORE_COMP0_B4_CTL, 0x37},
+ {MSM89XX_CDC_CORE_COMP0_B5_CTL, 0x7F},
+ {MSM89XX_CDC_CORE_COMP0_B6_CTL, 0x00},
+ {MSM89XX_CDC_CORE_COMP0_SHUT_DOWN_STATUS, 0x03},
+ {MSM89XX_CDC_CORE_COMP0_FS_CFG, 0x03},
+ {MSM89XX_CDC_CORE_COMP0_DELAY_BUF_CTL, 0x02},
+ {MSM89XX_CDC_CORE_DEBUG_DESER1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_DEBUG_DESER2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_DEBUG_B1_CTL_CFG, 0x00},
+ {MSM89XX_CDC_CORE_DEBUG_B2_CTL_CFG, 0x00},
+ {MSM89XX_CDC_CORE_DEBUG_B3_CTL_CFG, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_B4_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_B4_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_B5_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_B5_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_B6_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_B6_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_B7_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_B7_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_B8_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_B8_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_CTL, 0x40},
+ {MSM89XX_CDC_CORE_IIR2_CTL, 0x40},
+ {MSM89XX_CDC_CORE_IIR1_GAIN_TIMER_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_GAIN_TIMER_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_COEF_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_IIR2_COEF_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_RX1_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_RX1_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_RX1_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_RX2_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_RX2_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_RX2_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_RX3_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_RX3_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_TX_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_EQ1_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_EQ1_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_EQ1_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_EQ1_B4_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_EQ2_B1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_EQ2_B2_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_EQ2_B3_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_EQ2_B4_CTL, 0x00},
+ {MSM89XX_CDC_CORE_CONN_TX_I2S_SD1_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TX1_VOL_CTL_TIMER, 0x00},
+ {MSM89XX_CDC_CORE_TX2_VOL_CTL_TIMER, 0x00},
+ {MSM89XX_CDC_CORE_TX3_VOL_CTL_TIMER, 0x00},
+ {MSM89XX_CDC_CORE_TX4_VOL_CTL_TIMER, 0x00},
+ {MSM89XX_CDC_CORE_TX1_VOL_CTL_GAIN, 0x00},
+ {MSM89XX_CDC_CORE_TX2_VOL_CTL_GAIN, 0x00},
+ {MSM89XX_CDC_CORE_TX3_VOL_CTL_GAIN, 0x00},
+ {MSM89XX_CDC_CORE_TX4_VOL_CTL_GAIN, 0x00},
+ {MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG, 0x00},
+ {MSM89XX_CDC_CORE_TX2_VOL_CTL_CFG, 0x00},
+ {MSM89XX_CDC_CORE_TX3_VOL_CTL_CFG, 0x00},
+ {MSM89XX_CDC_CORE_TX4_VOL_CTL_CFG, 0x00},
+ {MSM89XX_CDC_CORE_TX1_MUX_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TX2_MUX_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TX3_MUX_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TX4_MUX_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TX1_CLK_FS_CTL, 0x03},
+ {MSM89XX_CDC_CORE_TX2_CLK_FS_CTL, 0x03},
+ {MSM89XX_CDC_CORE_TX3_CLK_FS_CTL, 0x03},
+ {MSM89XX_CDC_CORE_TX4_CLK_FS_CTL, 0x03},
+ {MSM89XX_CDC_CORE_TX1_DMIC_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TX2_DMIC_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TX3_DMIC_CTL, 0x00},
+ {MSM89XX_CDC_CORE_TX4_DMIC_CTL, 0x00},
+};
+
+static struct reg_default
+ msm89xx_pmic_cdc_defaults[MSM89XX_PMIC_CDC_CACHE_SIZE] = {
+ {MSM89XX_PMIC_DIGITAL_REVISION1, 0x00},
+ {MSM89XX_PMIC_DIGITAL_REVISION2, 0x00},
+ {MSM89XX_PMIC_DIGITAL_PERPH_TYPE, 0x23},
+ {MSM89XX_PMIC_DIGITAL_PERPH_SUBTYPE, 0x01},
+ {MSM89XX_PMIC_DIGITAL_INT_RT_STS, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_SET_TYPE, 0xFF},
+ {MSM89XX_PMIC_DIGITAL_INT_POLARITY_HIGH, 0xFF},
+ {MSM89XX_PMIC_DIGITAL_INT_POLARITY_LOW, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_LATCHED_CLR, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_EN_SET, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_EN_CLR, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_LATCHED_STS, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_PENDING_STS, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_MID_SEL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_PRIORITY, 0x00},
+ {MSM89XX_PMIC_DIGITAL_GPIO_MODE, 0x00},
+ {MSM89XX_PMIC_DIGITAL_PIN_CTL_OE, 0x01},
+ {MSM89XX_PMIC_DIGITAL_PIN_CTL_DATA, 0x00},
+ {MSM89XX_PMIC_DIGITAL_PIN_STATUS, 0x00},
+ {MSM89XX_PMIC_DIGITAL_HDRIVE_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_RST_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_TOP_CLK_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_CONN_TX1_CTL, 0x02},
+ {MSM89XX_PMIC_DIGITAL_CDC_CONN_TX2_CTL, 0x02},
+ {MSM89XX_PMIC_DIGITAL_CDC_CONN_HPHR_DAC_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_CONN_RX1_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_CONN_RX2_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_CONN_RX3_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_CONN_RX_LB_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_CDC_RX_CTL1, 0x7C},
+ {MSM89XX_PMIC_DIGITAL_CDC_RX_CTL2, 0x7C},
+ {MSM89XX_PMIC_DIGITAL_CDC_RX_CTL3, 0x7C},
+ {MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA0, 0x00},
+ {MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA1, 0x00},
+ {MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA2, 0x00},
+ {MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA3, 0x00},
+ {MSM89XX_PMIC_DIGITAL_DIG_DEBUG_CTL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_DIG_DEBUG_EN, 0x00},
+ {MSM89XX_PMIC_DIGITAL_SPARE_0, 0x00},
+ {MSM89XX_PMIC_DIGITAL_SPARE_1, 0x00},
+ {MSM89XX_PMIC_DIGITAL_SPARE_2, 0x00},
+ {MSM89XX_PMIC_DIGITAL_SEC_ACCESS, 0x00},
+ {MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL1, 0x00},
+ {MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL2, 0x02},
+ {MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3, 0x05},
+ {MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL4, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_TEST1, 0x00},
+ {MSM89XX_PMIC_DIGITAL_INT_TEST_VAL, 0x00},
+ {MSM89XX_PMIC_DIGITAL_TRIM_NUM, 0x00},
+ {MSM89XX_PMIC_DIGITAL_TRIM_CTRL, 0x00},
+ {MSM89XX_PMIC_ANALOG_REVISION1, 0x00},
+ {MSM89XX_PMIC_ANALOG_REVISION2, 0x00},
+ {MSM89XX_PMIC_ANALOG_REVISION3, 0x00},
+ {MSM89XX_PMIC_ANALOG_REVISION4, 0x00},
+ {MSM89XX_PMIC_ANALOG_PERPH_TYPE, 0x23},
+ {MSM89XX_PMIC_ANALOG_PERPH_SUBTYPE, 0x09},
+ {MSM89XX_PMIC_ANALOG_INT_RT_STS, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_SET_TYPE, 0x3F},
+ {MSM89XX_PMIC_ANALOG_INT_POLARITY_HIGH, 0x3F},
+ {MSM89XX_PMIC_ANALOG_INT_POLARITY_LOW, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_LATCHED_CLR, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_EN_SET, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_EN_CLR, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_LATCHED_STS, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_PENDING_STS, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_MID_SEL, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_PRIORITY, 0x00},
+ {MSM89XX_PMIC_ANALOG_MICB_1_EN, 0x00},
+ {MSM89XX_PMIC_ANALOG_MICB_1_VAL, 0x20},
+ {MSM89XX_PMIC_ANALOG_MICB_1_CTL, 0x00},
+ {MSM89XX_PMIC_ANALOG_MICB_1_INT_RBIAS, 0x49},
+ {MSM89XX_PMIC_ANALOG_MICB_2_EN, 0x20},
+ {MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL_2, 0x00},
+ {MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL, 0x00},
+ {MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1, 0x35},
+ {MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, 0x08},
+ {MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL, 0x00},
+ {MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER, 0x98},
+ {MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL, 0x00},
+ {MSM89XX_PMIC_ANALOG_MBHC_BTN1_ZDETM_CTL, 0x20},
+ {MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL, 0x40},
+ {MSM89XX_PMIC_ANALOG_MBHC_BTN3_CTL, 0x61},
+ {MSM89XX_PMIC_ANALOG_MBHC_BTN4_CTL, 0x80},
+ {MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT, 0x00},
+ {MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT, 0x00},
+ {MSM89XX_PMIC_ANALOG_TX_1_EN, 0x03},
+ {MSM89XX_PMIC_ANALOG_TX_2_EN, 0x03},
+ {MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_1, 0xBF},
+ {MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_2, 0x8C},
+ {MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL, 0x00},
+ {MSM89XX_PMIC_ANALOG_TX_1_2_OPAMP_BIAS, 0x6B},
+ {MSM89XX_PMIC_ANALOG_TX_1_2_TXFE_CLKDIV, 0x51},
+ {MSM89XX_PMIC_ANALOG_TX_3_EN, 0x02},
+ {MSM89XX_PMIC_ANALOG_NCP_EN, 0x26},
+ {MSM89XX_PMIC_ANALOG_NCP_CLK, 0x23},
+ {MSM89XX_PMIC_ANALOG_NCP_DEGLITCH, 0x5B},
+ {MSM89XX_PMIC_ANALOG_NCP_FBCTRL, 0x08},
+ {MSM89XX_PMIC_ANALOG_NCP_BIAS, 0x29},
+ {MSM89XX_PMIC_ANALOG_NCP_VCTRL, 0x24},
+ {MSM89XX_PMIC_ANALOG_NCP_TEST, 0x00},
+ {MSM89XX_PMIC_ANALOG_NCP_CLIM_ADDR, 0xD5},
+ {MSM89XX_PMIC_ANALOG_RX_CLOCK_DIVIDER, 0xE8},
+ {MSM89XX_PMIC_ANALOG_RX_COM_OCP_CTL, 0xCF},
+ {MSM89XX_PMIC_ANALOG_RX_COM_OCP_COUNT, 0x6E},
+ {MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC, 0x18},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_PA, 0x5A},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_LDO_OCP, 0x69},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_CNP, 0x29},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN, 0x80},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_CTL, 0xDA},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_TIME, 0x16},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_L_TEST, 0x00},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_L_PA_DAC_CTL, 0x20},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_R_TEST, 0x00},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_R_PA_DAC_CTL, 0x20},
+ {MSM89XX_PMIC_ANALOG_RX_EAR_CTL, 0x12},
+ {MSM89XX_PMIC_ANALOG_RX_ATEST, 0x00},
+ {MSM89XX_PMIC_ANALOG_RX_HPH_STATUS, 0x0C},
+ {MSM89XX_PMIC_ANALOG_RX_EAR_STATUS, 0x00},
+ {MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL, 0x00},
+ {MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL, 0x00},
+ {MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x83},
+ {MSM89XX_PMIC_ANALOG_SPKR_DRV_CLIP_DET, 0x91},
+ {MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL, 0x29},
+ {MSM89XX_PMIC_ANALOG_SPKR_ANA_BIAS_SET, 0x4D},
+ {MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL, 0xE1},
+ {MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL, 0x1E},
+ {MSM89XX_PMIC_ANALOG_SPKR_DRV_MISC, 0xCB},
+ {MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG, 0x00},
+ {MSM89XX_PMIC_ANALOG_CURRENT_LIMIT, 0x02},
+ {MSM89XX_PMIC_ANALOG_OUTPUT_VOLTAGE, 0x14},
+ {MSM89XX_PMIC_ANALOG_BYPASS_MODE, 0x00},
+ {MSM89XX_PMIC_ANALOG_BOOST_EN_CTL, 0x1F},
+ {MSM89XX_PMIC_ANALOG_SLOPE_COMP_IP_ZERO, 0x8C},
+ {MSM89XX_PMIC_ANALOG_RDSON_MAX_DUTY_CYCLE, 0xC0},
+ {MSM89XX_PMIC_ANALOG_BOOST_TEST1_1, 0x00},
+ {MSM89XX_PMIC_ANALOG_BOOST_TEST_2, 0x00},
+ {MSM89XX_PMIC_ANALOG_SPKR_SAR_STATUS, 0x00},
+ {MSM89XX_PMIC_ANALOG_SPKR_DRV_STATUS, 0x00},
+ {MSM89XX_PMIC_ANALOG_PBUS_ADD_CSR, 0x00},
+ {MSM89XX_PMIC_ANALOG_PBUS_ADD_SEL, 0x00},
+ {MSM89XX_PMIC_ANALOG_SEC_ACCESS, 0x00},
+ {MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL1, 0x00},
+ {MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL2, 0x01},
+ {MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3, 0x05},
+ {MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL4, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_TEST1, 0x00},
+ {MSM89XX_PMIC_ANALOG_INT_TEST_VAL, 0x00},
+ {MSM89XX_PMIC_ANALOG_TRIM_NUM, 0x04},
+ {MSM89XX_PMIC_ANALOG_TRIM_CTRL1, 0x00},
+ {MSM89XX_PMIC_ANALOG_TRIM_CTRL2, 0x00},
+ {MSM89XX_PMIC_ANALOG_TRIM_CTRL3, 0x00},
+ {MSM89XX_PMIC_ANALOG_TRIM_CTRL4, 0x00},
+};
+
+static bool msm89xx_cdc_core_readable_reg(struct device *dev, unsigned int reg)
+{
+ return msm89xx_cdc_core_reg_readable[reg];
+}
+
+static bool msm89xx_pmic_cdc_readable_reg(struct device *dev, unsigned int reg)
+{
+ return msm89xx_pmic_cdc_reg_readable[reg];
+}
+
+static bool msm89xx_cdc_core_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MSM89XX_CDC_CORE_RX1_B1_CTL:
+ case MSM89XX_CDC_CORE_RX2_B1_CTL:
+ case MSM89XX_CDC_CORE_RX3_B1_CTL:
+ case MSM89XX_CDC_CORE_RX1_B6_CTL:
+ case MSM89XX_CDC_CORE_RX2_B6_CTL:
+ case MSM89XX_CDC_CORE_RX3_B6_CTL:
+ case MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG:
+ case MSM89XX_CDC_CORE_TX2_VOL_CTL_CFG:
+ case MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL:
+ case MSM89XX_CDC_CORE_IIR2_COEF_B1_CTL:
+ case MSM89XX_CDC_CORE_CLK_MCLK_CTL:
+ case MSM89XX_CDC_CORE_CLK_PDM_CTL:
+ case MSM89XX_PMIC_ANALOG_BYPASS_MODE:
+ case MSM89XX_PMIC_ANALOG_BOOST_EN_CTL:
+ case MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL:
+ case MSM89XX_PMIC_ANALOG_CURRENT_LIMIT:
+ case MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL:
+ case MSM89XX_PMIC_ANALOG_NCP_FBCTRL:
+ case MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool msm89xx_pmic_cdc_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MSM89XX_PMIC_DIGITAL_REVISION1:
+ case MSM89XX_PMIC_DIGITAL_REVISION2:
+ case MSM89XX_PMIC_DIGITAL_PERPH_TYPE:
+ case MSM89XX_PMIC_DIGITAL_PERPH_SUBTYPE:
+ case MSM89XX_PMIC_DIGITAL_INT_RT_STS:
+ case MSM89XX_PMIC_DIGITAL_INT_SET_TYPE:
+ case MSM89XX_PMIC_DIGITAL_INT_POLARITY_HIGH:
+ case MSM89XX_PMIC_DIGITAL_INT_POLARITY_LOW:
+ case MSM89XX_PMIC_DIGITAL_INT_LATCHED_STS:
+ case MSM89XX_PMIC_DIGITAL_INT_PENDING_STS:
+ case MSM89XX_PMIC_DIGITAL_PIN_STATUS:
+ case MSM89XX_PMIC_DIGITAL_SEC_ACCESS:
+ case MSM89XX_PMIC_ANALOG_SEC_ACCESS:
+ case MSM89XX_PMIC_ANALOG_REVISION1:
+ case MSM89XX_PMIC_ANALOG_REVISION2:
+ case MSM89XX_PMIC_ANALOG_REVISION3:
+ case MSM89XX_PMIC_ANALOG_REVISION4:
+ case MSM89XX_PMIC_ANALOG_PERPH_TYPE:
+ case MSM89XX_PMIC_ANALOG_PERPH_SUBTYPE:
+ case MSM89XX_PMIC_ANALOG_INT_RT_STS:
+ case MSM89XX_PMIC_ANALOG_INT_SET_TYPE:
+ case MSM89XX_PMIC_ANALOG_INT_POLARITY_HIGH:
+ case MSM89XX_PMIC_ANALOG_INT_POLARITY_LOW:
+ case MSM89XX_PMIC_ANALOG_INT_LATCHED_STS:
+ case MSM89XX_PMIC_ANALOG_INT_PENDING_STS:
+ case MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT:
+ case MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT:
+ case MSM89XX_PMIC_ANALOG_RX_HPH_STATUS:
+ case MSM89XX_PMIC_ANALOG_RX_EAR_STATUS:
+ case MSM89XX_PMIC_ANALOG_SPKR_SAR_STATUS:
+ case MSM89XX_PMIC_ANALOG_SPKR_DRV_STATUS:
+ return true;
+ default:
+ return false;
+ }
+}
+
+struct regmap_config msm89xx_pmic_cdc_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .max_register = MSM89XX_PMIC_CDC_CACHE_SIZE,
+ .fast_io = true,
+ .reg_defaults = msm89xx_pmic_cdc_defaults,
+ .num_reg_defaults = ARRAY_SIZE(msm89xx_pmic_cdc_defaults),
+ .readable_reg = msm89xx_pmic_cdc_readable_reg,
+ .volatile_reg = msm89xx_pmic_cdc_volatile_reg,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_format_endian = REGMAP_ENDIAN_NATIVE,
+ .val_format_endian = REGMAP_ENDIAN_NATIVE,
+ .can_multi_write = true,
+ .lock = enable_digital_callback,
+ .unlock = disable_digital_callback,
+
+};
+
+struct regmap_config msm89xx_cdc_core_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+
+ .max_register = MSM89XX_CDC_CORE_CACHE_SIZE,
+ .reg_defaults = msm89xx_cdc_core_defaults,
+ .num_reg_defaults = ARRAY_SIZE(msm89xx_cdc_core_defaults),
+ .readable_reg = msm89xx_cdc_core_readable_reg,
+ .volatile_reg = msm89xx_cdc_core_volatile_reg,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_format_endian = REGMAP_ENDIAN_NATIVE,
+ .val_format_endian = REGMAP_ENDIAN_NATIVE,
+ .can_multi_write = true,
+};
diff --git a/sound/soc/codecs/msm8x16/msm8x16-wcd-tables.c b/sound/soc/codecs/msm8x16/msm8x16-wcd-tables.c
new file mode 100644
index 000000000000..b969639b10eb
--- /dev/null
+++ b/sound/soc/codecs/msm8x16/msm8x16-wcd-tables.c
@@ -0,0 +1,263 @@
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include "msm8x16-wcd.h"
+
+const u8 msm89xx_pmic_cdc_reg_readable[MSM89XX_PMIC_CDC_CACHE_SIZE] = {
+ [MSM89XX_PMIC_DIGITAL_REVISION1] = 1,
+ [MSM89XX_PMIC_DIGITAL_REVISION2] = 1,
+ [MSM89XX_PMIC_DIGITAL_PERPH_TYPE] = 1,
+ [MSM89XX_PMIC_DIGITAL_PERPH_SUBTYPE] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_RT_STS] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_SET_TYPE] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_POLARITY_HIGH] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_POLARITY_LOW] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_EN_SET] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_EN_CLR] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_LATCHED_STS] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_PENDING_STS] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_MID_SEL] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_PRIORITY] = 1,
+ [MSM89XX_PMIC_DIGITAL_GPIO_MODE] = 1,
+ [MSM89XX_PMIC_DIGITAL_PIN_CTL_OE] = 1,
+ [MSM89XX_PMIC_DIGITAL_PIN_CTL_DATA] = 1,
+ [MSM89XX_PMIC_DIGITAL_PIN_STATUS] = 1,
+ [MSM89XX_PMIC_DIGITAL_HDRIVE_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_RST_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_TOP_CLK_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_CONN_TX1_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_CONN_TX2_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_CONN_HPHR_DAC_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_CONN_RX1_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_CONN_RX2_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_CONN_RX3_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_CONN_RX_LB_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_RX_CTL1] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_RX_CTL2] = 1,
+ [MSM89XX_PMIC_DIGITAL_CDC_RX_CTL3] = 1,
+ [MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA0] = 1,
+ [MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA1] = 1,
+ [MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA2] = 1,
+ [MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA3] = 1,
+ [MSM89XX_PMIC_DIGITAL_DIG_DEBUG_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_SPARE_0] = 1,
+ [MSM89XX_PMIC_DIGITAL_SPARE_1] = 1,
+ [MSM89XX_PMIC_DIGITAL_SPARE_2] = 1,
+ [MSM89XX_PMIC_ANALOG_REVISION1] = 1,
+ [MSM89XX_PMIC_ANALOG_REVISION2] = 1,
+ [MSM89XX_PMIC_ANALOG_REVISION3] = 1,
+ [MSM89XX_PMIC_ANALOG_REVISION4] = 1,
+ [MSM89XX_PMIC_ANALOG_PERPH_TYPE] = 1,
+ [MSM89XX_PMIC_ANALOG_PERPH_SUBTYPE] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_RT_STS] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_SET_TYPE] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_POLARITY_HIGH] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_POLARITY_LOW] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_EN_SET] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_EN_CLR] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_LATCHED_STS] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_PENDING_STS] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_MID_SEL] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_PRIORITY] = 1,
+ [MSM89XX_PMIC_ANALOG_MICB_1_EN] = 1,
+ [MSM89XX_PMIC_ANALOG_MICB_1_VAL] = 1,
+ [MSM89XX_PMIC_ANALOG_MICB_1_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_MICB_1_INT_RBIAS] = 1,
+ [MSM89XX_PMIC_ANALOG_MICB_2_EN] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL_2] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_BTN1_ZDETM_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_BTN3_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_BTN4_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT] = 1,
+ [MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_1_EN] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_2_EN] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_1] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_2] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_1_2_OPAMP_BIAS] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_1_2_TXFE_CLKDIV] = 1,
+ [MSM89XX_PMIC_ANALOG_TX_3_EN] = 1,
+ [MSM89XX_PMIC_ANALOG_NCP_EN] = 1,
+ [MSM89XX_PMIC_ANALOG_NCP_CLK] = 1,
+ [MSM89XX_PMIC_ANALOG_NCP_DEGLITCH] = 1,
+ [MSM89XX_PMIC_ANALOG_NCP_FBCTRL] = 1,
+ [MSM89XX_PMIC_ANALOG_NCP_BIAS] = 1,
+ [MSM89XX_PMIC_ANALOG_NCP_VCTRL] = 1,
+ [MSM89XX_PMIC_ANALOG_NCP_TEST] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_CLOCK_DIVIDER] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_COM_OCP_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_COM_OCP_COUNT] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_PA] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_LDO_OCP] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_CNP] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_TIME] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_L_TEST] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_L_PA_DAC_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_R_TEST] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_R_PA_DAC_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_EAR_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_ATEST] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_HPH_STATUS] = 1,
+ [MSM89XX_PMIC_ANALOG_RX_EAR_STATUS] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_DRV_CLIP_DET] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_ANA_BIAS_SET] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_DRV_MISC] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG] = 1,
+ [MSM89XX_PMIC_ANALOG_CURRENT_LIMIT] = 1,
+ [MSM89XX_PMIC_ANALOG_OUTPUT_VOLTAGE] = 1,
+ [MSM89XX_PMIC_ANALOG_BYPASS_MODE] = 1,
+ [MSM89XX_PMIC_ANALOG_BOOST_EN_CTL] = 1,
+ [MSM89XX_PMIC_ANALOG_SLOPE_COMP_IP_ZERO] = 1,
+ [MSM89XX_PMIC_ANALOG_RDSON_MAX_DUTY_CYCLE] = 1,
+ [MSM89XX_PMIC_ANALOG_BOOST_TEST1_1] = 1,
+ [MSM89XX_PMIC_ANALOG_BOOST_TEST_2] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_SAR_STATUS] = 1,
+ [MSM89XX_PMIC_ANALOG_SPKR_DRV_STATUS] = 1,
+ [MSM89XX_PMIC_ANALOG_PBUS_ADD_CSR] = 1,
+ [MSM89XX_PMIC_ANALOG_PBUS_ADD_SEL] = 1,
+ [MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL] = 1,
+ [MSM89XX_PMIC_DIGITAL_INT_LATCHED_CLR] = 1,
+ [MSM89XX_PMIC_ANALOG_INT_LATCHED_CLR] = 1,
+ [MSM89XX_PMIC_ANALOG_NCP_CLIM_ADDR] = 1,
+ [MSM89XX_PMIC_DIGITAL_SEC_ACCESS] = 1,
+ [MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3] = 1,
+ [MSM89XX_PMIC_ANALOG_SEC_ACCESS] = 1,
+};
+
+const u8 msm89xx_cdc_core_reg_readable[MSM89XX_CDC_CORE_CACHE_SIZE] = {
+ [MSM89XX_CDC_CORE_CLK_RX_RESET_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_TX_RESET_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_DMIC_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_RX_I2S_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_TX_I2S_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_OTHR_RESET_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_OTHR_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_RX_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_MCLK_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_PDM_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_SD_CTL] = 1,
+ [MSM89XX_CDC_CORE_CLK_WSA_VI_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX1_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX2_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX3_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX1_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX2_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX3_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX1_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX2_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX3_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX1_B4_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX2_B4_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX3_B4_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX1_B5_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX2_B5_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX3_B5_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX1_B6_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX2_B6_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX3_B6_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX1_VOL_CTL_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX2_VOL_CTL_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX3_VOL_CTL_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX1_VOL_CTL_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX2_VOL_CTL_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_RX3_VOL_CTL_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_TOP_GAIN_UPDATE] = 1,
+ [MSM89XX_CDC_CORE_TOP_CTL] = 1,
+ [MSM89XX_CDC_CORE_DEBUG_DESER1_CTL] = 1,
+ [MSM89XX_CDC_CORE_DEBUG_DESER2_CTL] = 1,
+ [MSM89XX_CDC_CORE_DEBUG_B1_CTL_CFG] = 1,
+ [MSM89XX_CDC_CORE_DEBUG_B2_CTL_CFG] = 1,
+ [MSM89XX_CDC_CORE_DEBUG_B3_CTL_CFG] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_B4_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_B4_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_B5_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_B5_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_B6_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_B6_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_B7_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_B7_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_B8_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_B8_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_GAIN_TIMER_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_GAIN_TIMER_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_COEF_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_IIR2_COEF_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_RX1_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_RX1_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_RX1_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_RX2_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_RX2_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_RX2_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_RX3_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_RX3_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_TX_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_EQ1_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_EQ1_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_EQ1_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_EQ1_B4_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_EQ2_B1_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_EQ2_B2_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_EQ2_B3_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_EQ2_B4_CTL] = 1,
+ [MSM89XX_CDC_CORE_CONN_TX_I2S_SD1_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX1_VOL_CTL_TIMER] = 1,
+ [MSM89XX_CDC_CORE_TX2_VOL_CTL_TIMER] = 1,
+ [MSM89XX_CDC_CORE_TX3_VOL_CTL_TIMER] = 1,
+ [MSM89XX_CDC_CORE_TX4_VOL_CTL_TIMER] = 1,
+ [MSM89XX_CDC_CORE_TX1_VOL_CTL_GAIN] = 1,
+ [MSM89XX_CDC_CORE_TX2_VOL_CTL_GAIN] = 1,
+ [MSM89XX_CDC_CORE_TX3_VOL_CTL_GAIN] = 1,
+ [MSM89XX_CDC_CORE_TX4_VOL_CTL_GAIN] = 1,
+ [MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG] = 1,
+ [MSM89XX_CDC_CORE_TX2_VOL_CTL_CFG] = 1,
+ [MSM89XX_CDC_CORE_TX3_VOL_CTL_CFG] = 1,
+ [MSM89XX_CDC_CORE_TX4_VOL_CTL_CFG] = 1,
+ [MSM89XX_CDC_CORE_TX1_MUX_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX2_MUX_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX3_MUX_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX4_MUX_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX1_CLK_FS_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX2_CLK_FS_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX3_CLK_FS_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX4_CLK_FS_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX1_DMIC_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX2_DMIC_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX3_DMIC_CTL] = 1,
+ [MSM89XX_CDC_CORE_TX4_DMIC_CTL] = 1,
+};
diff --git a/sound/soc/codecs/msm8x16/msm8x16-wcd.c b/sound/soc/codecs/msm8x16/msm8x16-wcd.c
new file mode 100644
index 000000000000..481e1efdf015
--- /dev/null
+++ b/sound/soc/codecs/msm8x16/msm8x16-wcd.c
@@ -0,0 +1,6037 @@
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/printk.h>
+#include <linux/ratelimit.h>
+#include <linux/debugfs.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/spmi.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/qdsp6v2/apr.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <sound/q6afe-v2.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <sound/q6core.h>
+#include <soc/qcom/subsystem_notif.h>
+#include "msm8x16-wcd.h"
+#include "../wcd-mbhc-v2.h"
+#include "msm8916-wcd-irq.h"
+
+#define DRV_NAME "msm-codec"
+#define MSM89XX_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
+#define MSM89XX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+#define NUM_INTERPOLATORS 3
+#define BITS_PER_REG 8
+#define MSM89XX_TX_PORT_NUMBER 4
+
+#define MSM89XX_I2S_MASTER_MODE_MASK 0x08
+#define MSM89XX_DIGITAL_CODEC_BASE_ADDR 0x771C000
+#define PMIC_SLAVE_ID_0 0
+#define PMIC_SLAVE_ID_1 1
+
+#define PMIC_MBG_OK 0x2C08
+#define PMIC_LDO7_EN_CTL 0x4646
+#define MASK_MSB_BIT 0x80
+
+#define CODEC_DT_MAX_PROP_SIZE 40
+#define MSM89XX_DIGITAL_CODEC_REG_SIZE 0x400
+#define MAX_ON_DEMAND_SUPPLY_NAME_LENGTH 64
+
+#define MCLK_RATE_9P6MHZ 9600000
+#define MCLK_RATE_12P288MHZ 12288000
+
+#define BUS_DOWN 1
+
+/*
+ *50 Milliseconds sufficient for DSP bring up in the modem
+ * after Sub System Restart
+ */
+#define ADSP_STATE_READY_TIMEOUT_MS 50
+
+#define HPHL_PA_DISABLE (0x01 << 1)
+#define HPHR_PA_DISABLE (0x01 << 2)
+#define EAR_PA_DISABLE (0x01 << 3)
+#define SPKR_PA_DISABLE (0x01 << 4)
+
+enum {
+ BOOST_SWITCH = 0,
+ BOOST_ALWAYS,
+ BYPASS_ALWAYS,
+ BOOST_ON_FOREVER,
+};
+
+#define EAR_PMD 0
+#define EAR_PMU 1
+#define SPK_PMD 2
+#define SPK_PMU 3
+
+#define MICBIAS_DEFAULT_VAL 1800000
+#define MICBIAS_MIN_VAL 1600000
+#define MICBIAS_STEP_SIZE 50000
+
+#define DEFAULT_BOOST_VOLTAGE 5000
+#define MIN_BOOST_VOLTAGE 4000
+#define MAX_BOOST_VOLTAGE 5550
+#define BOOST_VOLTAGE_STEP 50
+
+#define MSM89XX_MBHC_BTN_COARSE_ADJ 100 /* in mV */
+#define MSM89XX_MBHC_BTN_FINE_ADJ 12 /* in mV */
+
+#define VOLTAGE_CONVERTER(value, min_value, step_size)\
+ ((value - min_value)/step_size)
+
+enum {
+ AIF1_PB = 0,
+ AIF1_CAP,
+ AIF2_VIFEED,
+ NUM_CODEC_DAIS,
+};
+
+enum {
+ RX_MIX1_INP_SEL_ZERO = 0,
+ RX_MIX1_INP_SEL_IIR1,
+ RX_MIX1_INP_SEL_IIR2,
+ RX_MIX1_INP_SEL_RX1,
+ RX_MIX1_INP_SEL_RX2,
+ RX_MIX1_INP_SEL_RX3,
+};
+
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
+static struct snd_soc_dai_driver msm8x16_wcd_i2s_dai[];
+/* By default enable the internal speaker boost */
+static bool spkr_boost_en = true;
+
+#define MSM89XX_ACQUIRE_LOCK(x) \
+ mutex_lock_nested(&x, SINGLE_DEPTH_NESTING)
+
+#define MSM89XX_RELEASE_LOCK(x) mutex_unlock(&x)
+
+
+/* Codec supports 2 IIR filters */
+enum {
+ IIR1 = 0,
+ IIR2,
+ IIR_MAX,
+};
+
+/* Codec supports 5 bands */
+enum {
+ BAND1 = 0,
+ BAND2,
+ BAND3,
+ BAND4,
+ BAND5,
+ BAND_MAX,
+};
+
+struct hpf_work {
+ struct msm8x16_wcd_priv *msm8x16_wcd;
+ u32 decimator;
+ u8 tx_hpf_cut_of_freq;
+ struct delayed_work dwork;
+};
+
+static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
+
+static char on_demand_supply_name[][MAX_ON_DEMAND_SUPPLY_NAME_LENGTH] = {
+ "cdc-vdd-mic-bias",
+};
+
+static unsigned long rx_digital_gain_reg[] = {
+ MSM89XX_CDC_CORE_RX1_VOL_CTL_B2_CTL,
+ MSM89XX_CDC_CORE_RX2_VOL_CTL_B2_CTL,
+ MSM89XX_CDC_CORE_RX3_VOL_CTL_B2_CTL,
+};
+
+static unsigned long tx_digital_gain_reg[] = {
+ MSM89XX_CDC_CORE_TX1_VOL_CTL_GAIN,
+ MSM89XX_CDC_CORE_TX2_VOL_CTL_GAIN,
+};
+
+enum {
+ MSM89XX_SPMI_DIGITAL = 0,
+ MSM89XX_SPMI_ANALOG,
+ MSM89XX_CODEC_CORE,
+ MAX_MSM89XX_DEVICE
+};
+
+static struct wcd_mbhc_register
+ wcd_mbhc_registers[WCD_MBHC_REG_FUNC_MAX] = {
+
+ WCD_MBHC_REGISTER("WCD_MBHC_L_DET_EN",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1, 0x80, 7, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_GND_DET_EN",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1, 0x40, 6, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_MECH_DETECTION_TYPE",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1, 0x20, 5, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_MIC_CLAMP_CTL",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1, 0x18, 3, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_ELECT_DETECTION_TYPE",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1, 0x01, 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HS_L_DET_PULL_UP_CTRL",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, 0xC0, 6, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, 0x20, 5, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HPHL_PLUG_TYPE",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, 0x10, 4, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_GND_PLUG_TYPE",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, 0x08, 3, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_SW_HPH_LP_100K_TO_GND",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, 0x01, 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_ELECT_SCHMT_ISRC",
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, 0x06, 1, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_FSM_EN",
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL, 0x80, 7, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_INSREM_DBNC",
+ MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER, 0xF0, 4, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_BTN_DBNC",
+ MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER, 0x0C, 2, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HS_VREF",
+ MSM89XX_PMIC_ANALOG_MBHC_BTN3_CTL, 0x03, 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HS_COMP_RESULT",
+ MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT, 0x01,
+ 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_MIC_SCHMT_RESULT",
+ MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT, 0x02,
+ 1, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HPHL_SCHMT_RESULT",
+ MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT, 0x08,
+ 3, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HPHR_SCHMT_RESULT",
+ MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT, 0x04,
+ 2, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_OCP_FSM_EN",
+ MSM89XX_PMIC_ANALOG_RX_COM_OCP_CTL, 0x10, 4, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_BTN_RESULT",
+ MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT, 0xFF, 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_BTN_ISRC_CTL",
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL, 0x70, 4, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_ELECT_RESULT",
+ MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT, 0xFF,
+ 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_MICB_CTRL",
+ MSM89XX_PMIC_ANALOG_MICB_2_EN, 0xC0, 6, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HPH_CNP_WG_TIME",
+ MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_TIME, 0xFC, 2, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HPHR_PA_EN",
+ MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN, 0x10, 4, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HPHL_PA_EN",
+ MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN, 0x20, 5, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_HPH_PA_EN",
+ MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN, 0x30, 4, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_SWCH_LEVEL_REMOVE",
+ MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT,
+ 0x10, 4, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_MOISTURE_VREF",
+ 0, 0, 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_PULLDOWN_CTRL",
+ MSM89XX_PMIC_ANALOG_MICB_2_EN, 0x20, 5, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_ANC_DET_EN",
+ 0, 0, 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_FSM_STATUS",
+ 0, 0, 0, 0),
+ WCD_MBHC_REGISTER("WCD_MBHC_MUX_CTL",
+ 0, 0, 0, 0),
+};
+
+struct msm8x16_wcd_spmi {
+ struct spmi_device *spmi;
+ int base;
+};
+
+/* Multiply gain_adj and offset by 1000 and 100 to avoid float arithmetic */
+static const struct wcd_imped_i_ref imped_i_ref[] = {
+ {I_h4_UA, 8, 800, 9000, 10000},
+ {I_pt5_UA, 10, 100, 990, 4600},
+ {I_14_UA, 17, 14, 1050, 700},
+ {I_l4_UA, 10, 4, 1165, 110},
+ {I_1_UA, 0, 1, 1200, 65},
+};
+
+static const struct wcd_mbhc_intr intr_ids = {
+ .mbhc_sw_intr = MSM89XX_IRQ_MBHC_HS_DET,
+ .mbhc_btn_press_intr = MSM89XX_IRQ_MBHC_PRESS,
+ .mbhc_btn_release_intr = MSM89XX_IRQ_MBHC_RELEASE,
+ .mbhc_hs_ins_intr = MSM89XX_IRQ_MBHC_INSREM_DET1,
+ .mbhc_hs_rem_intr = MSM89XX_IRQ_MBHC_INSREM_DET,
+ .hph_left_ocp = MSM89XX_IRQ_HPHL_OCP,
+ .hph_right_ocp = MSM89XX_IRQ_HPHR_OCP,
+};
+
+static int msm_digcdc_clock_control(bool flag);
+static int msm8x16_wcd_dt_parse_vreg_info(struct device *dev,
+ struct msm8x16_wcd_regulator *vreg,
+ const char *vreg_name, bool ondemand);
+static struct msm8x16_wcd_pdata *msm8x16_wcd_populate_dt_pdata(
+ struct device *dev);
+static int msm8x16_wcd_enable_ext_mb_source(struct snd_soc_codec *codec,
+ bool turn_on);
+static void msm8x16_trim_btn_reg(struct snd_soc_codec *codec);
+static void msm8x16_wcd_set_micb_v(struct snd_soc_codec *codec);
+static void msm8x16_wcd_set_boost_v(struct snd_soc_codec *codec);
+static void msm8x16_wcd_set_auto_zeroing(struct snd_soc_codec *codec,
+ bool enable);
+static void msm8x16_wcd_configure_cap(struct snd_soc_codec *codec,
+ bool micbias1, bool micbias2);
+static bool msm8x16_wcd_use_mb(struct snd_soc_codec *codec);
+
+struct msm8x16_wcd_spmi msm8x16_wcd_modules[MAX_MSM89XX_DEVICE];
+
+static void *adsp_state_notifier;
+
+static struct snd_soc_codec *registered_codec;
+static struct snd_soc_codec *registered_digcodec;
+
+static int get_codec_version(struct msm8x16_wcd_priv *msm8x16_wcd)
+{
+ if (msm8x16_wcd->codec_version == DIANGU)
+ return DIANGU;
+ else if (msm8x16_wcd->codec_version == CAJON_2_0)
+ return CAJON_2_0;
+ else if (msm8x16_wcd->codec_version == CAJON)
+ return CAJON;
+ else if (msm8x16_wcd->codec_version == CONGA)
+ return CONGA;
+ else if (msm8x16_wcd->pmic_rev == TOMBAK_2_0)
+ return TOMBAK_2_0;
+ else if (msm8x16_wcd->pmic_rev == TOMBAK_1_0)
+ return TOMBAK_1_0;
+
+ pr_err("%s: unsupported codec version\n", __func__);
+ return UNSUPPORTED;
+}
+
+static int msm_digcdc_clock_control(bool flag)
+{
+ int ret = -EINVAL;
+ struct msm8916_asoc_mach_data *pdata = NULL;
+
+ pdata = snd_soc_card_get_drvdata(registered_codec->component.card);
+
+ if (flag) {
+ mutex_lock(&pdata->cdc_mclk_mutex);
+ if (atomic_read(&pdata->mclk_enabled) == false) {
+ if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
+ pdata->digital_cdc_clk.clk_val =
+ pdata->mclk_freq;
+ ret = afe_set_digital_codec_core_clock(
+ AFE_PORT_ID_PRIMARY_MI2S_RX,
+ &pdata->digital_cdc_clk);
+ } else {
+ pdata->digital_cdc_core_clk.enable = 1;
+ ret = afe_set_lpass_clock_v2(
+ AFE_PORT_ID_PRIMARY_MI2S_RX,
+ &pdata->digital_cdc_core_clk);
+ }
+ if (ret < 0) {
+ pr_err("failed to enable the MCLK\n");
+ goto err;
+ }
+ pr_err("enabled digital codec core clk\n");
+ atomic_set(&pdata->mclk_enabled, true);
+ schedule_delayed_work(&pdata->disable_mclk_work, 50);
+ }
+err:
+ mutex_unlock(&pdata->cdc_mclk_mutex);
+ return ret;
+ }
+ return 0;
+}
+
+void enable_digital_callback(void *flag)
+{
+ msm_digcdc_clock_control(true);
+}
+
+void disable_digital_callback(void *flag)
+{
+ msm_digcdc_clock_control(false);
+}
+
+static int snd_soc_read_wrapper(struct snd_soc_codec *codec, u16 reg)
+{
+ int ret = -EINVAL;
+ struct msm8x16_wcd *msm8x16_wcd = codec->control_data;
+
+ pr_err("%s reg = %x\n", __func__, reg);
+ mutex_lock(&msm8x16_wcd->io_lock);
+ if (MSM89XX_IS_PMIC_CDC_REG(reg))
+ ret = snd_soc_read(codec, reg);
+ else if (MSM89XX_IS_CDC_CORE_REG(reg))
+ ret = snd_soc_read(registered_digcodec, reg);
+ mutex_unlock(&msm8x16_wcd->io_lock);
+
+ return ret;
+}
+
+static int snd_soc_write_wrapper(struct snd_soc_codec *codec, u16 reg, u8 val)
+{
+ int ret = -EINVAL;
+ struct msm8x16_wcd *msm8x16_wcd = codec->control_data;
+
+ pr_err("%s reg = %x\n", __func__, reg);
+ mutex_lock(&msm8x16_wcd->io_lock);
+ if (MSM89XX_IS_PMIC_CDC_REG(reg))
+ ret = snd_soc_write(codec, reg, val);
+ else if (MSM89XX_IS_CDC_CORE_REG(reg))
+ ret = snd_soc_write(registered_digcodec, reg, val);
+ mutex_unlock(&msm8x16_wcd->io_lock);
+
+ return ret;
+}
+
+static int snd_soc_update_bits_wrapper(struct snd_soc_codec *codec,
+ u16 reg, u8 mask, u8 val)
+{
+ int ret = -EINVAL;
+ struct msm8x16_wcd *msm8x16_wcd = codec->control_data;
+
+ pr_err("%s reg = %x\n", __func__, reg);
+ mutex_lock(&msm8x16_wcd->io_lock);
+ if (MSM89XX_IS_PMIC_CDC_REG(reg))
+ ret = snd_soc_update_bits(codec, reg, mask, val);
+ else if (MSM89XX_IS_CDC_CORE_REG(reg))
+ ret = snd_soc_update_bits(registered_digcodec, reg, mask, val);
+ mutex_unlock(&msm8x16_wcd->io_lock);
+
+ return ret;
+}
+
+static void wcd_mbhc_meas_imped(struct snd_soc_codec *codec,
+ s16 *impedance_l, s16 *impedance_r)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if ((msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_BOTH) ||
+ (msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_HPHL)) {
+ /* Enable ZDET_L_MEAS_EN */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x08, 0x08);
+ /* Wait for 2ms for measurement to complete */
+ usleep_range(2000, 2100);
+ /* Read Left impedance value from Result1 */
+ *impedance_l = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT);
+ /* Enable ZDET_R_MEAS_EN */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x08, 0x00);
+ }
+ if ((msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_BOTH) ||
+ (msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_HPHR)) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x04, 0x04);
+ /* Wait for 2ms for measurement to complete */
+ usleep_range(2000, 2100);
+ /* Read Right impedance value from Result1 */
+ *impedance_r = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x04, 0x00);
+ }
+}
+
+static void msm8x16_set_ref_current(struct snd_soc_codec *codec,
+ enum wcd_curr_ref curr_ref)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ pr_err("%s: curr_ref: %d\n", __func__, curr_ref);
+
+ if (get_codec_version(msm8x16_wcd) < CAJON)
+ pr_err("%s: Setting ref current not required\n", __func__);
+
+ msm8x16_wcd->imped_i_ref = imped_i_ref[curr_ref];
+
+ switch (curr_ref) {
+ case I_h4_UA:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN,
+ 0x07, 0x01);
+ break;
+ case I_pt5_UA:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN,
+ 0x07, 0x04);
+ break;
+ case I_14_UA:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN,
+ 0x07, 0x03);
+ break;
+ case I_l4_UA:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN,
+ 0x07, 0x01);
+ break;
+ case I_1_UA:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN,
+ 0x07, 0x00);
+ break;
+ default:
+ pr_err("%s: No ref current set\n", __func__);
+ break;
+ }
+}
+
+static bool msm8x16_adj_ref_current(struct snd_soc_codec *codec,
+ s16 *impedance_l, s16 *impedance_r)
+{
+ int i = 2;
+ s16 compare_imp = 0;
+
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_HPHR)
+ compare_imp = *impedance_r;
+ else
+ compare_imp = *impedance_l;
+
+ if (get_codec_version(msm8x16_wcd) < CAJON) {
+ pr_err("%s: Reference current adjustment not required\n",
+ __func__);
+ return false;
+ }
+
+ while (compare_imp < imped_i_ref[i].min_val) {
+ msm8x16_set_ref_current(codec,
+ imped_i_ref[++i].curr_ref);
+ wcd_mbhc_meas_imped(codec,
+ impedance_l, impedance_r);
+ compare_imp = (msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_HPHR)
+ ? *impedance_r : *impedance_l;
+ }
+
+ return true;
+}
+
+void msm8x16_wcd_spk_ext_pa_cb(
+ int (*codec_spk_ext_pa)(struct snd_soc_codec *codec,
+ int enable), struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ pr_err("%s: Enter\n", __func__);
+ msm8x16_wcd->codec_spk_ext_pa_cb = codec_spk_ext_pa;
+}
+
+void msm8x16_wcd_hph_comp_cb(
+ int (*codec_hph_comp_gpio)(bool enable), struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ pr_err("%s: Enter\n", __func__);
+ msm8x16_wcd->codec_hph_comp_gpio = codec_hph_comp_gpio;
+}
+
+static void msm8x16_wcd_compute_impedance(struct snd_soc_codec *codec, s16 l,
+ s16 r, uint32_t *zl, uint32_t *zr, bool high)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ uint32_t rl = 0, rr = 0;
+ struct wcd_imped_i_ref R = msm8x16_wcd->imped_i_ref;
+ int codec_ver = get_codec_version(msm8x16_wcd);
+
+ switch (codec_ver) {
+ case TOMBAK_1_0:
+ case TOMBAK_2_0:
+ case CONGA:
+ if (high) {
+ pr_err("%s: This plug has high range impedance\n",
+ __func__);
+ rl = (uint32_t)(((100 * (l * 400 - 200))/96) - 230);
+ rr = (uint32_t)(((100 * (r * 400 - 200))/96) - 230);
+ } else {
+ pr_err("%s: This plug has low range impedance\n",
+ __func__);
+ rl = (uint32_t)(((1000 * (l * 2 - 1))/1165) - (13/10));
+ rr = (uint32_t)(((1000 * (r * 2 - 1))/1165) - (13/10));
+ }
+ break;
+ case CAJON:
+ case CAJON_2_0:
+ case DIANGU:
+ if (msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_HPHL) {
+ rr = (uint32_t)(((DEFAULT_MULTIPLIER * (10 * r - 5)) -
+ (DEFAULT_OFFSET * DEFAULT_GAIN))/DEFAULT_GAIN);
+ rl = (uint32_t)(((10000 * (R.multiplier * (10 * l - 5)))
+ - R.offset * R.gain_adj)/(R.gain_adj * 100));
+ } else if (msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_HPHR) {
+ rr = (uint32_t)(((10000 * (R.multiplier * (10 * r - 5)))
+ - R.offset * R.gain_adj)/(R.gain_adj * 100));
+ rl = (uint32_t)(((DEFAULT_MULTIPLIER * (10 * l - 5))-
+ (DEFAULT_OFFSET * DEFAULT_GAIN))/DEFAULT_GAIN);
+ } else if (msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_NONE) {
+ rr = (uint32_t)(((DEFAULT_MULTIPLIER * (10 * r - 5)) -
+ (DEFAULT_OFFSET * DEFAULT_GAIN))/DEFAULT_GAIN);
+ rl = (uint32_t)(((DEFAULT_MULTIPLIER * (10 * l - 5))-
+ (DEFAULT_OFFSET * DEFAULT_GAIN))/DEFAULT_GAIN);
+ } else {
+ rr = (uint32_t)(((10000 * (R.multiplier * (10 * r - 5)))
+ - R.offset * R.gain_adj)/(R.gain_adj * 100));
+ rl = (uint32_t)(((10000 * (R.multiplier * (10 * l - 5)))
+ - R.offset * R.gain_adj)/(R.gain_adj * 100));
+ }
+ break;
+ default:
+ pr_err("%s: No codec mentioned\n", __func__);
+ break;
+ }
+ *zl = rl;
+ *zr = rr;
+}
+
+static struct firmware_cal *msm8x16_wcd_get_hwdep_fw_cal(
+ struct snd_soc_codec *codec,
+ enum wcd_cal_type type)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd;
+ struct firmware_cal *hwdep_cal;
+
+ if (!codec) {
+ pr_err("%s: NULL codec pointer\n", __func__);
+ return NULL;
+ }
+ msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ hwdep_cal = wcdcal_get_fw_cal(msm8x16_wcd->fw_data, type);
+ if (!hwdep_cal) {
+ dev_err(codec->dev, "%s: cal not sent by %d\n",
+ __func__, type);
+ return NULL;
+ }
+ return hwdep_cal;
+}
+
+static void wcd9xxx_spmi_irq_control(struct snd_soc_codec *codec,
+ int irq, bool enable)
+{
+ if (enable)
+ wcd9xxx_spmi_enable_irq(irq);
+ else
+ wcd9xxx_spmi_disable_irq(irq);
+}
+
+static void msm8x16_mbhc_clk_setup(struct snd_soc_codec *codec,
+ bool enable)
+{
+ if (enable)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x08, 0x08);
+ else
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x08, 0x00);
+}
+
+static int msm8x16_mbhc_map_btn_code_to_num(struct snd_soc_codec *codec)
+{
+ int btn_code;
+ int btn;
+
+ btn_code = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT);
+
+ switch (btn_code) {
+ case 0:
+ btn = 0;
+ break;
+ case 1:
+ btn = 1;
+ break;
+ case 3:
+ btn = 2;
+ break;
+ case 7:
+ btn = 3;
+ break;
+ case 15:
+ btn = 4;
+ break;
+ default:
+ btn = -EINVAL;
+ break;
+ };
+
+ return btn;
+}
+
+static bool msm8x16_spmi_lock_sleep(struct wcd_mbhc *mbhc, bool lock)
+{
+ if (lock)
+ return wcd9xxx_spmi_lock_sleep();
+ wcd9xxx_spmi_unlock_sleep();
+ return 0;
+}
+
+static bool msm8x16_wcd_micb_en_status(struct wcd_mbhc *mbhc, int micb_num)
+{
+ if (micb_num == MIC_BIAS_1)
+ return (snd_soc_read_wrapper(mbhc->codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_EN) &
+ 0x80);
+ if (micb_num == MIC_BIAS_2)
+ return (snd_soc_read_wrapper(mbhc->codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN) &
+ 0x80);
+ return false;
+}
+
+static void msm8x16_wcd_enable_master_bias(struct snd_soc_codec *codec,
+ bool enable)
+{
+ if (enable)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL,
+ 0x30, 0x30);
+ else
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL,
+ 0x30, 0x00);
+}
+
+static void msm8x16_wcd_mbhc_common_micb_ctrl(struct snd_soc_codec *codec,
+ int event, bool enable)
+{
+ u16 reg;
+ u8 mask;
+ u8 val;
+
+ switch (event) {
+ case MBHC_COMMON_MICB_PRECHARGE:
+ reg = MSM89XX_PMIC_ANALOG_MICB_1_CTL;
+ mask = 0x60;
+ val = (enable ? 0x60 : 0x00);
+ break;
+ case MBHC_COMMON_MICB_SET_VAL:
+ reg = MSM89XX_PMIC_ANALOG_MICB_1_VAL;
+ mask = 0xFF;
+ val = (enable ? 0xC0 : 0x00);
+ break;
+ case MBHC_COMMON_MICB_TAIL_CURR:
+ reg = MSM89XX_PMIC_ANALOG_MICB_1_EN;
+ mask = 0x04;
+ val = (enable ? 0x04 : 0x00);
+ break;
+ };
+ snd_soc_update_bits_wrapper(codec, reg, mask, val);
+}
+
+static void msm8x16_wcd_mbhc_internal_micbias_ctrl(struct snd_soc_codec *codec,
+ int micbias_num, bool enable)
+{
+ if (micbias_num == 1) {
+ if (enable)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_INT_RBIAS,
+ 0x10, 0x10);
+ else
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_INT_RBIAS,
+ 0x10, 0x00);
+ }
+}
+
+static bool msm8x16_wcd_mbhc_hph_pa_on_status(struct snd_soc_codec *codec)
+{
+ return (snd_soc_read_wrapper(codec, MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN) &
+ 0x30) ? true : false;
+}
+
+static void msm8x16_wcd_mbhc_program_btn_thr(struct snd_soc_codec *codec,
+ s16 *btn_low, s16 *btn_high,
+ int num_btn, bool is_micbias)
+{
+ int i;
+ u32 course, fine, reg_val;
+ u16 reg_addr = MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL;
+ s16 *btn_voltage;
+
+ btn_voltage = ((is_micbias) ? btn_high : btn_low);
+
+ for (i = 0; i < num_btn; i++) {
+ course = (btn_voltage[i] / MSM89XX_MBHC_BTN_COARSE_ADJ);
+ fine = ((btn_voltage[i] % MSM89XX_MBHC_BTN_COARSE_ADJ) /
+ MSM89XX_MBHC_BTN_FINE_ADJ);
+
+ reg_val = (course << 5) | (fine << 2);
+ snd_soc_update_bits_wrapper(codec, reg_addr, 0xFC, reg_val);
+ pr_err("%s: course: %d fine: %d reg_addr: %x reg_val: %x\n",
+ __func__, course, fine, reg_addr, reg_val);
+ reg_addr++;
+ }
+}
+
+static void msm8x16_wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
+ uint32_t *zr)
+{
+ struct snd_soc_codec *codec = mbhc->codec;
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ s16 impedance_l, impedance_r;
+ s16 impedance_l_fixed;
+ s16 reg0, reg1, reg2, reg3, reg4;
+ bool high = false;
+ bool min_range_used = false;
+
+ WCD_MBHC_RSC_ASSERT_LOCKED(mbhc);
+ reg0 = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER);
+ reg1 = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL);
+ reg2 = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2);
+ reg3 = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN);
+ reg4 = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL);
+
+ msm8x16_wcd->imped_det_pin = WCD_MBHC_DET_BOTH;
+ mbhc->hph_type = WCD_MBHC_HPH_NONE;
+
+ /* disable FSM and micbias and enable pullup*/
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x80, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN,
+ 0xA5, 0x25);
+ /*
+ * Enable legacy electrical detection current sources
+ * and disable fast ramp and enable manual switching
+ * of extra capacitance
+ */
+ pr_err("%s: Setup for impedance det\n", __func__);
+
+ msm8x16_set_ref_current(codec, I_h4_UA);
+
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2,
+ 0x06, 0x02);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER,
+ 0x02, 0x02);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL,
+ 0x02, 0x00);
+
+ pr_err("%s: Start performing impedance detection\n",
+ __func__);
+
+ wcd_mbhc_meas_imped(codec, &impedance_l, &impedance_r);
+
+ if (impedance_l > 2 || impedance_r > 2) {
+ high = true;
+ if (!mbhc->mbhc_cfg->mono_stero_detection) {
+ /* Set ZDET_CHG to 0 to discharge ramp */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x02, 0x00);
+ /* wait 40ms for the discharge ramp to complete */
+ usleep_range(40000, 40100);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
+ 0x03, 0x00);
+ msm8x16_wcd->imped_det_pin = (impedance_l > 2 &&
+ impedance_r > 2) ?
+ WCD_MBHC_DET_NONE :
+ ((impedance_l > 2) ?
+ WCD_MBHC_DET_HPHR :
+ WCD_MBHC_DET_HPHL);
+ if (msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_NONE)
+ goto exit;
+ } else {
+ if (get_codec_version(msm8x16_wcd) >= CAJON) {
+ if (impedance_l == 63 && impedance_r == 63) {
+ pr_err("%s: HPHL and HPHR are floating\n",
+ __func__);
+ msm8x16_wcd->imped_det_pin =
+ WCD_MBHC_DET_NONE;
+ mbhc->hph_type = WCD_MBHC_HPH_NONE;
+ } else if (impedance_l == 63
+ && impedance_r < 63) {
+ pr_err("%s: Mono HS with HPHL floating\n",
+ __func__);
+ msm8x16_wcd->imped_det_pin =
+ WCD_MBHC_DET_HPHR;
+ mbhc->hph_type = WCD_MBHC_HPH_MONO;
+ } else if (impedance_r == 63 &&
+ impedance_l < 63) {
+ pr_err("%s: Mono HS with HPHR floating\n",
+ __func__);
+ msm8x16_wcd->imped_det_pin =
+ WCD_MBHC_DET_HPHL;
+ mbhc->hph_type = WCD_MBHC_HPH_MONO;
+ } else if (impedance_l > 3 && impedance_r > 3 &&
+ (impedance_l == impedance_r)) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2,
+ 0x06, 0x06);
+ wcd_mbhc_meas_imped(codec, &impedance_l,
+ &impedance_r);
+ if (impedance_r == impedance_l)
+ pr_err("%s: Mono Headset\n",
+ __func__);
+ msm8x16_wcd->imped_det_pin =
+ WCD_MBHC_DET_NONE;
+ mbhc->hph_type =
+ WCD_MBHC_HPH_MONO;
+ } else {
+ pr_err("%s: STEREO headset is found\n",
+ __func__);
+ msm8x16_wcd->imped_det_pin =
+ WCD_MBHC_DET_BOTH;
+ mbhc->hph_type = WCD_MBHC_HPH_STEREO;
+ }
+ }
+ }
+ }
+
+ msm8x16_set_ref_current(codec, I_pt5_UA);
+ msm8x16_set_ref_current(codec, I_14_UA);
+
+ /* Enable RAMP_L, RAMP_R & ZDET_CHG*/
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
+ 0x03, 0x03);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x02, 0x02);
+ /* wait for 50msec for the HW to apply ramp on HPHL and HPHR */
+ usleep_range(50000, 50100);
+ /* Enable ZDET_DISCHG_CAP_CTL to add extra capacitance */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x01, 0x01);
+ /* wait for 5msec for the voltage to get stable */
+ usleep_range(5000, 5100);
+
+
+ wcd_mbhc_meas_imped(codec, &impedance_l, &impedance_r);
+
+ min_range_used = msm8x16_adj_ref_current(codec,
+ &impedance_l, &impedance_r);
+ if (!mbhc->mbhc_cfg->mono_stero_detection) {
+ /* Set ZDET_CHG to 0 to discharge ramp */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x02, 0x00);
+ /* wait for 40msec for the capacitor to discharge */
+ usleep_range(40000, 40100);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
+ 0x03, 0x00);
+ goto exit;
+ }
+
+ /* we are setting ref current to the minimun range or the measured
+ * value larger than the minimum value, so min_range_used is true.
+ * If the headset is mono headset with either HPHL or HPHR floating
+ * then we have already done the mono stereo detection and do not
+ * need to continue further.
+ */
+
+ if (!min_range_used ||
+ msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_HPHL ||
+ msm8x16_wcd->imped_det_pin == WCD_MBHC_DET_HPHR)
+ goto exit;
+
+
+ /* Disable Set ZDET_CONN_RAMP_L and enable ZDET_CONN_FIXED_L */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
+ 0x02, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN1_ZDETM_CTL,
+ 0x02, 0x02);
+ /* Set ZDET_CHG to 0 */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x02, 0x00);
+ /* wait for 40msec for the capacitor to discharge */
+ usleep_range(40000, 40100);
+
+ /* Set ZDET_CONN_RAMP_R to 0 */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
+ 0x01, 0x00);
+ /* Enable ZDET_L_MEAS_EN */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x08, 0x08);
+ /* wait for 2msec for the HW to compute left inpedance value */
+ usleep_range(2000, 2100);
+ /* Read Left impedance value from Result1 */
+ impedance_l_fixed = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT);
+ /* Disable ZDET_L_MEAS_EN */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x08, 0x00);
+ /*
+ * Assume impedance_l is L1, impedance_l_fixed is L2.
+ * If the following condition is met, we can take this
+ * headset as mono one with impedance of L2.
+ * Otherwise, take it as stereo with impedance of L1.
+ * Condition:
+ * abs[(L2-0.5L1)/(L2+0.5L1)] < abs [(L2-L1)/(L2+L1)]
+ */
+ if ((abs(impedance_l_fixed - impedance_l/2) *
+ (impedance_l_fixed + impedance_l)) >=
+ (abs(impedance_l_fixed - impedance_l) *
+ (impedance_l_fixed + impedance_l/2))) {
+ pr_err("%s: STEREO plug type detected\n",
+ __func__);
+ mbhc->hph_type = WCD_MBHC_HPH_STEREO;
+ } else {
+ pr_err("%s: MONO plug type detected\n",
+ __func__);
+ mbhc->hph_type = WCD_MBHC_HPH_MONO;
+ impedance_l = impedance_l_fixed;
+ }
+ /* Enable ZDET_CHG */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x02, 0x02);
+ /* wait for 10msec for the capacitor to charge */
+ usleep_range(10000, 10100);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
+ 0x02, 0x02);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN1_ZDETM_CTL,
+ 0x02, 0x00);
+ /* Set ZDET_CHG to 0 to discharge HPHL */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL,
+ 0x02, 0x00);
+ /* wait for 40msec for the capacitor to discharge */
+ usleep_range(40000, 40100);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL,
+ 0x02, 0x00);
+
+exit:
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL, reg4);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN, reg3);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL, reg1);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER, reg0);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2, reg2);
+ msm8x16_wcd_compute_impedance(codec, impedance_l, impedance_r,
+ zl, zr, high);
+
+ pr_err("%s: RL %d ohm, RR %d ohm\n", __func__, *zl, *zr);
+ pr_err("%s: Impedance detection completed\n", __func__);
+}
+
+static int msm8x16_register_notifier(struct snd_soc_codec *codec,
+ struct notifier_block *nblock,
+ bool enable)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd =
+ snd_soc_codec_get_drvdata(codec);
+
+ if (enable)
+ return blocking_notifier_chain_register(&msm8x16_wcd->notifier,
+ nblock);
+ return blocking_notifier_chain_unregister(
+ &msm8x16_wcd->notifier, nblock);
+}
+
+static int msm8x16_wcd_request_irq(struct snd_soc_codec *codec,
+ int irq, irq_handler_t handler,
+ const char *name, void *data)
+{
+ return wcd9xxx_spmi_request_irq(irq, handler, name, data);
+}
+
+static int msm8x16_wcd_free_irq(struct snd_soc_codec *codec,
+ int irq, void *data)
+{
+ return wcd9xxx_spmi_free_irq(irq, data);
+}
+
+static const struct wcd_mbhc_cb mbhc_cb = {
+ .enable_mb_source = msm8x16_wcd_enable_ext_mb_source,
+ .trim_btn_reg = msm8x16_trim_btn_reg,
+ .compute_impedance = msm8x16_wcd_mbhc_calc_impedance,
+ .set_micbias_value = msm8x16_wcd_set_micb_v,
+ .set_auto_zeroing = msm8x16_wcd_set_auto_zeroing,
+ .get_hwdep_fw_cal = msm8x16_wcd_get_hwdep_fw_cal,
+ .set_cap_mode = msm8x16_wcd_configure_cap,
+ .register_notifier = msm8x16_register_notifier,
+ .request_irq = msm8x16_wcd_request_irq,
+ .irq_control = wcd9xxx_spmi_irq_control,
+ .free_irq = msm8x16_wcd_free_irq,
+ .clk_setup = msm8x16_mbhc_clk_setup,
+ .map_btn_code_to_num = msm8x16_mbhc_map_btn_code_to_num,
+ .lock_sleep = msm8x16_spmi_lock_sleep,
+ .micbias_enable_status = msm8x16_wcd_micb_en_status,
+ .mbhc_bias = msm8x16_wcd_enable_master_bias,
+ .mbhc_common_micb_ctrl = msm8x16_wcd_mbhc_common_micb_ctrl,
+ .micb_internal = msm8x16_wcd_mbhc_internal_micbias_ctrl,
+ .hph_pa_on_status = msm8x16_wcd_mbhc_hph_pa_on_status,
+ .set_btn_thr = msm8x16_wcd_mbhc_program_btn_thr,
+ .extn_use_mb = msm8x16_wcd_use_mb,
+};
+
+static const uint32_t wcd_imped_val[] = {4, 8, 12, 13, 16,
+ 20, 24, 28, 32,
+ 36, 40, 44, 48};
+
+void msm8x16_notifier_call(struct snd_soc_codec *codec,
+ const enum wcd_notify_event event)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ pr_err("%s: notifier call event %d\n", __func__, event);
+ blocking_notifier_call_chain(&msm8x16_wcd->notifier, event,
+ &msm8x16_wcd->mbhc);
+}
+
+static void msm8x16_wcd_boost_on(struct snd_soc_codec *codec)
+{
+ u8 dest = 0x00;
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+
+ if ((dest & MASK_MSB_BIT) == 0) {
+ pr_err("PMIC MBG not ON, enable codec hw_en MB bit again\n");
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL, 0x30);
+ /* Allow 1ms for PMIC MBG state to be updated */
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ }
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3,
+ 0x0F, 0x0F);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SEC_ACCESS,
+ 0xA5);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3,
+ 0x0F);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL,
+ 0x30);
+ if (get_codec_version(msm8x16_wcd) < CAJON_2_0) {
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_CURRENT_LIMIT,
+ 0x82);
+ } else {
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_CURRENT_LIMIT,
+ 0xA2);
+ }
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
+ 0x69, 0x69);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG,
+ 0x01, 0x01);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SLOPE_COMP_IP_ZERO,
+ 0x88, 0x88);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL,
+ 0x03, 0x03);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL,
+ 0xE1, 0xE1);
+ if (get_codec_version(msm8x16_wcd) < CAJON_2_0) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x20, 0x20);
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BOOST_EN_CTL,
+ 0xDF, 0xDF);
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ } else {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BOOST_EN_CTL,
+ 0x40, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x20, 0x20);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BOOST_EN_CTL,
+ 0x80, 0x80);
+ usleep_range(500, 510);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BOOST_EN_CTL,
+ 0x40, 0x40);
+ usleep_range(500, 510);
+ }
+}
+
+static void msm8x16_wcd_boost_off(struct snd_soc_codec *codec)
+{
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BOOST_EN_CTL,
+ 0xDF, 0x5F);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x20, 0x00);
+}
+
+static void msm8x16_wcd_bypass_on(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (get_codec_version(msm8x16_wcd) < CAJON_2_0) {
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SEC_ACCESS,
+ 0xA5);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3,
+ 0x07);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x02, 0x02);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x01, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x40, 0x40);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x80, 0x80);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BOOST_EN_CTL,
+ 0xDF, 0xDF);
+ } else {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x20, 0x20);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x20, 0x20);
+ }
+}
+
+static void msm8x16_wcd_bypass_off(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (get_codec_version(msm8x16_wcd) < CAJON_2_0) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BOOST_EN_CTL,
+ 0x80, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x80, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x02, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x40, 0x00);
+ } else {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_BYPASS_MODE,
+ 0x20, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x20, 0x00);
+ }
+}
+
+static void msm8x16_wcd_boost_mode_sequence(struct snd_soc_codec *codec,
+ int flag)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (flag == EAR_PMU) {
+ switch (msm8x16_wcd->boost_option) {
+ case BOOST_SWITCH:
+ if (msm8x16_wcd->ear_pa_boost_set) {
+ msm8x16_wcd_boost_off(codec);
+ msm8x16_wcd_bypass_on(codec);
+ }
+ break;
+ case BOOST_ALWAYS:
+ msm8x16_wcd_boost_on(codec);
+ break;
+ case BYPASS_ALWAYS:
+ msm8x16_wcd_bypass_on(codec);
+ break;
+ case BOOST_ON_FOREVER:
+ msm8x16_wcd_boost_on(codec);
+ break;
+ default:
+ pr_err("%s: invalid boost option: %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ break;
+ }
+ } else if (flag == EAR_PMD) {
+ switch (msm8x16_wcd->boost_option) {
+ case BOOST_SWITCH:
+ if (msm8x16_wcd->ear_pa_boost_set)
+ msm8x16_wcd_bypass_off(codec);
+ break;
+ case BOOST_ALWAYS:
+ msm8x16_wcd_boost_off(codec);
+ /* 80ms for EAR boost to settle down */
+ msleep(80);
+ break;
+ case BYPASS_ALWAYS:
+ /* nothing to do as bypass on always */
+ break;
+ case BOOST_ON_FOREVER:
+ /* nothing to do as boost on forever */
+ break;
+ default:
+ pr_err("%s: invalid boost option: %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ break;
+ }
+ } else if (flag == SPK_PMU) {
+ switch (msm8x16_wcd->boost_option) {
+ case BOOST_SWITCH:
+ if (msm8x16_wcd->spk_boost_set) {
+ msm8x16_wcd_bypass_off(codec);
+ msm8x16_wcd_boost_on(codec);
+ }
+ break;
+ case BOOST_ALWAYS:
+ msm8x16_wcd_boost_on(codec);
+ break;
+ case BYPASS_ALWAYS:
+ msm8x16_wcd_bypass_on(codec);
+ break;
+ case BOOST_ON_FOREVER:
+ msm8x16_wcd_boost_on(codec);
+ break;
+ default:
+ pr_err("%s: invalid boost option: %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ break;
+ }
+ } else if (flag == SPK_PMD) {
+ switch (msm8x16_wcd->boost_option) {
+ case BOOST_SWITCH:
+ if (msm8x16_wcd->spk_boost_set) {
+ msm8x16_wcd_boost_off(codec);
+ /*
+ * Add 40 ms sleep for the spk
+ * boost to settle down
+ */
+ msleep(40);
+ }
+ break;
+ case BOOST_ALWAYS:
+ msm8x16_wcd_boost_off(codec);
+ /*
+ * Add 40 ms sleep for the spk
+ * boost to settle down
+ */
+ msleep(40);
+ break;
+ case BYPASS_ALWAYS:
+ /* nothing to do as bypass on always */
+ break;
+ case BOOST_ON_FOREVER:
+ /* nothing to do as boost on forever */
+ break;
+ default:
+ pr_err("%s: invalid boost option: %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ break;
+ }
+ }
+}
+
+static int msm8x16_wcd_dt_parse_vreg_info(struct device *dev,
+ struct msm8x16_wcd_regulator *vreg, const char *vreg_name,
+ bool ondemand)
+{
+ int len, ret = 0;
+ const __be32 *prop;
+ char prop_name[CODEC_DT_MAX_PROP_SIZE];
+ struct device_node *regnode = NULL;
+ u32 prop_val;
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply",
+ vreg_name);
+ regnode = of_parse_phandle(dev->of_node, prop_name, 0);
+
+ if (!regnode) {
+ dev_err(dev, "Looking up %s property in node %s failed\n",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+
+ dev_err(dev, "Looking up %s property in node %s\n",
+ prop_name, dev->of_node->full_name);
+
+ vreg->name = vreg_name;
+ vreg->ondemand = ondemand;
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,%s-voltage", vreg_name);
+ prop = of_get_property(dev->of_node, prop_name, &len);
+
+ if (!prop || (len != (2 * sizeof(__be32)))) {
+ dev_err(dev, "%s %s property\n",
+ prop ? "invalid format" : "no", prop_name);
+ return -EINVAL;
+ }
+ vreg->min_uv = be32_to_cpup(&prop[0]);
+ vreg->max_uv = be32_to_cpup(&prop[1]);
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,%s-current", vreg_name);
+
+ ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -EFAULT;
+ }
+ vreg->optimum_ua = prop_val;
+
+ dev_err(dev, "%s: vol=[%d %d]uV, curr=[%d]uA, ond %d\n\n", vreg->name,
+ vreg->min_uv, vreg->max_uv, vreg->optimum_ua, vreg->ondemand);
+ return 0;
+}
+
+static void msm8x16_wcd_dt_parse_boost_info(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd_priv =
+ snd_soc_codec_get_drvdata(codec);
+ const char *prop_name = "qcom,cdc-boost-voltage";
+ int boost_voltage, ret;
+
+ ret = of_property_read_u32(codec->dev->of_node, prop_name,
+ &boost_voltage);
+ if (ret) {
+ dev_err(codec->dev, "Looking up %s property in node %s failed\n",
+ prop_name, codec->dev->of_node->full_name);
+ boost_voltage = DEFAULT_BOOST_VOLTAGE;
+ }
+ if (boost_voltage < MIN_BOOST_VOLTAGE ||
+ boost_voltage > MAX_BOOST_VOLTAGE) {
+ dev_err(codec->dev,
+ "Incorrect boost voltage. Reverting to default\n");
+ boost_voltage = DEFAULT_BOOST_VOLTAGE;
+ }
+
+ msm8x16_wcd_priv->boost_voltage =
+ VOLTAGE_CONVERTER(boost_voltage, MIN_BOOST_VOLTAGE,
+ BOOST_VOLTAGE_STEP);
+ dev_err(codec->dev, "Boost voltage value is: %d\n",
+ boost_voltage);
+}
+
+static void msm8x16_wcd_dt_parse_micbias_info(struct device *dev,
+ struct wcd9xxx_micbias_setting *micbias)
+{
+ const char *prop_name = "qcom,cdc-micbias-cfilt-mv";
+ int ret;
+
+ ret = of_property_read_u32(dev->of_node, prop_name,
+ &micbias->cfilt1_mv);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ micbias->cfilt1_mv = MICBIAS_DEFAULT_VAL;
+ }
+}
+
+static struct msm8x16_wcd_pdata *msm8x16_wcd_populate_dt_pdata(
+ struct device *dev)
+{
+ struct msm8x16_wcd_pdata *pdata;
+ int ret, static_cnt, ond_cnt, idx, i;
+ const char *name = NULL;
+ const char *static_prop_name = "qcom,cdc-static-supplies";
+ const char *ond_prop_name = "qcom,cdc-on-demand-supplies";
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return NULL;
+
+ static_cnt = of_property_count_strings(dev->of_node, static_prop_name);
+ if (IS_ERR_VALUE(static_cnt)) {
+ dev_err(dev, "%s: Failed to get static supplies %d\n", __func__,
+ static_cnt);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* On-demand supply list is an optional property */
+ ond_cnt = of_property_count_strings(dev->of_node, ond_prop_name);
+ if (IS_ERR_VALUE(ond_cnt))
+ ond_cnt = 0;
+
+ WARN_ON(static_cnt <= 0 || ond_cnt < 0);
+ if ((static_cnt + ond_cnt) > ARRAY_SIZE(pdata->regulator)) {
+ dev_err(dev, "%s: Num of supplies %u > max supported %zd\n",
+ __func__, (static_cnt + ond_cnt),
+ ARRAY_SIZE(pdata->regulator));
+ ret = -EINVAL;
+ goto err;
+ }
+
+ for (idx = 0; idx < static_cnt; idx++) {
+ ret = of_property_read_string_index(dev->of_node,
+ static_prop_name, idx,
+ &name);
+ if (ret) {
+ dev_err(dev, "%s: of read string %s idx %d error %d\n",
+ __func__, static_prop_name, idx, ret);
+ goto err;
+ }
+
+ dev_err(dev, "%s: Found static cdc supply %s\n", __func__,
+ name);
+ ret = msm8x16_wcd_dt_parse_vreg_info(dev,
+ &pdata->regulator[idx],
+ name, false);
+ if (ret) {
+ dev_err(dev, "%s:err parsing vreg for %s idx %d\n",
+ __func__, name, idx);
+ goto err;
+ }
+ }
+
+ for (i = 0; i < ond_cnt; i++, idx++) {
+ ret = of_property_read_string_index(dev->of_node, ond_prop_name,
+ i, &name);
+ if (ret) {
+ dev_err(dev, "%s: err parsing on_demand for %s idx %d\n",
+ __func__, ond_prop_name, i);
+ goto err;
+ }
+
+ dev_err(dev, "%s: Found on-demand cdc supply %s\n", __func__,
+ name);
+ ret = msm8x16_wcd_dt_parse_vreg_info(dev,
+ &pdata->regulator[idx],
+ name, true);
+ if (ret) {
+ dev_err(dev, "%s: err parsing vreg on_demand for %s idx %d\n",
+ __func__, name, idx);
+ goto err;
+ }
+ }
+ msm8x16_wcd_dt_parse_micbias_info(dev, &pdata->micbias);
+ return pdata;
+err:
+ devm_kfree(dev, pdata);
+ dev_err(dev, "%s: Failed to populate DT data ret = %d\n",
+ __func__, ret);
+ return NULL;
+}
+
+static int msm8x16_wcd_codec_enable_on_demand_supply(
+ struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ int ret = 0;
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ struct on_demand_supply *supply;
+
+ if (w->shift >= ON_DEMAND_SUPPLIES_MAX) {
+ dev_err(codec->dev, "%s: error index > MAX Demand supplies",
+ __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+ dev_err(codec->dev, "%s: supply: %s event: %d ref: %d\n",
+ __func__, on_demand_supply_name[w->shift], event,
+ atomic_read(&msm8x16_wcd->on_demand_list[w->shift].ref));
+
+ supply = &msm8x16_wcd->on_demand_list[w->shift];
+ WARN_ONCE(!supply->supply, "%s isn't defined\n",
+ on_demand_supply_name[w->shift]);
+ if (!supply->supply) {
+ dev_err(codec->dev, "%s: err supply not present ond for %d",
+ __func__, w->shift);
+ goto out;
+ }
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (atomic_inc_return(&supply->ref) == 1)
+ ret = regulator_enable(supply->supply);
+ if (ret)
+ dev_err(codec->dev, "%s: Failed to enable %s\n",
+ __func__,
+ on_demand_supply_name[w->shift]);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (atomic_read(&supply->ref) == 0) {
+ dev_err(codec->dev, "%s: %s supply has been disabled.\n",
+ __func__, on_demand_supply_name[w->shift]);
+ goto out;
+ }
+ if (atomic_dec_return(&supply->ref) == 0)
+ ret = regulator_disable(supply->supply);
+ if (ret)
+ dev_err(codec->dev, "%s: Failed to disable %s\n",
+ __func__,
+ on_demand_supply_name[w->shift]);
+ break;
+ default:
+ break;
+ }
+out:
+ return ret;
+}
+
+static int msm8x16_wcd_codec_enable_clock_block(struct snd_soc_codec *codec,
+ int enable)
+{
+ struct msm8916_asoc_mach_data *pdata = NULL;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ if (enable) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_MCLK_CTL, 0x01, 0x01);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_PDM_CTL, 0x03, 0x03);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL, 0x30, 0x30);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_RST_CTL, 0x80, 0x80);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_TOP_CLK_CTL, 0x0C, 0x0C);
+ if (pdata->mclk_freq == MCLK_RATE_12P288MHZ)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_TOP_CTL, 0x01, 0x00);
+ else if (pdata->mclk_freq == MCLK_RATE_9P6MHZ)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_TOP_CTL, 0x01, 0x01);
+ } else {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_TOP_CLK_CTL, 0x0C, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_PDM_CTL, 0x03, 0x00);
+
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: event = %d\n", __func__, event);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ msm8x16_wcd_codec_enable_clock_block(codec, 1);
+ if (!(strcmp(w->name, "EAR CP"))) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x80, 0x80);
+ msm8x16_wcd_boost_mode_sequence(codec, EAR_PMU);
+ } else if (get_codec_version(msm8x16_wcd) == DIANGU) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x80, 0x80);
+ } else {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0xC0, 0xC0);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ if (!(strcmp(w->name, "EAR CP"))) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x80, 0x00);
+ if (msm8x16_wcd->boost_option != BOOST_ALWAYS) {
+ dev_err(codec->dev,
+ "%s: boost_option:%d, tear down ear\n",
+ __func__, msm8x16_wcd->boost_option);
+ msm8x16_wcd_boost_mode_sequence(codec, EAR_PMD);
+ }
+ /*
+ * Reset pa select bit from ear to hph after ear pa
+ * is disabled and HPH DAC disable to reduce ear
+ * turn off pop and avoid HPH pop in concurrency
+ */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL, 0x80, 0x00);
+ } else {
+ if (get_codec_version(msm8x16_wcd) < DIANGU)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x40, 0x00);
+ if (msm8x16_wcd->rx_bias_count == 0)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x80, 0x00);
+ dev_err(codec->dev, "%s: rx_bias_count = %d\n",
+ __func__, msm8x16_wcd->rx_bias_count);
+ }
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_ear_pa_boost_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] =
+ (msm8x16_wcd->ear_pa_boost_set ? 1 : 0);
+ dev_err(codec->dev, "%s: msm8x16_wcd->ear_pa_boost_set = %d\n",
+ __func__, msm8x16_wcd->ear_pa_boost_set);
+ return 0;
+}
+
+static int msm8x16_wcd_ear_pa_boost_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd =
+ snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+ msm8x16_wcd->ear_pa_boost_set =
+ (ucontrol->value.integer.value[0] ? true : false);
+ return 0;
+}
+
+static int msm8x16_wcd_pa_gain_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 ear_pa_gain;
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+
+ ear_pa_gain = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL);
+
+ ear_pa_gain = (ear_pa_gain >> 5) & 0x1;
+
+ if (ear_pa_gain == 0x00) {
+ ucontrol->value.integer.value[0] = 0;
+ } else if (ear_pa_gain == 0x01) {
+ ucontrol->value.integer.value[0] = 1;
+ } else {
+ dev_err(codec->dev, "%s: ERROR: Unsupported Ear Gain = 0x%x\n",
+ __func__, ear_pa_gain);
+ return -EINVAL;
+ }
+
+ ucontrol->value.integer.value[0] = ear_pa_gain;
+ dev_err(codec->dev, "%s: ear_pa_gain = 0x%x\n",
+ __func__, ear_pa_gain);
+ return 0;
+}
+
+static int msm8x16_wcd_loopback_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8916_asoc_mach_data *pdata = NULL;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ return pdata->lb_mode;
+}
+
+static int msm8x16_wcd_loopback_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8916_asoc_mach_data *pdata = NULL;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 0:
+ pdata->lb_mode = false;
+ break;
+ case 1:
+ pdata->lb_mode = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int msm8x16_wcd_pa_gain_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 ear_pa_gain;
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 0:
+ ear_pa_gain = 0x00;
+ break;
+ case 1:
+ ear_pa_gain = 0x20;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits_wrapper(codec, MSM89XX_PMIC_ANALOG_RX_EAR_CTL,
+ 0x20, ear_pa_gain);
+ return 0;
+}
+
+static int msm8x16_wcd_hph_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (msm8x16_wcd->hph_mode == NORMAL_MODE) {
+ ucontrol->value.integer.value[0] = 0;
+ } else if (msm8x16_wcd->hph_mode == HD2_MODE) {
+ ucontrol->value.integer.value[0] = 1;
+ } else {
+ dev_err(codec->dev, "%s: ERROR: Default HPH Mode= %d\n",
+ __func__, msm8x16_wcd->hph_mode);
+ }
+
+ dev_err(codec->dev, "%s: msm8x16_wcd->hph_mode = %d\n", __func__,
+ msm8x16_wcd->hph_mode);
+ return 0;
+}
+
+static int msm8x16_wcd_hph_mode_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 0:
+ msm8x16_wcd->hph_mode = NORMAL_MODE;
+ break;
+ case 1:
+ if (get_codec_version(msm8x16_wcd) >= DIANGU)
+ msm8x16_wcd->hph_mode = HD2_MODE;
+ break;
+ default:
+ msm8x16_wcd->hph_mode = NORMAL_MODE;
+ break;
+ }
+ dev_err(codec->dev, "%s: msm8x16_wcd->hph_mode_set = %d\n",
+ __func__, msm8x16_wcd->hph_mode);
+ return 0;
+}
+
+static int msm8x16_wcd_boost_option_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (msm8x16_wcd->boost_option == BOOST_SWITCH) {
+ ucontrol->value.integer.value[0] = 0;
+ } else if (msm8x16_wcd->boost_option == BOOST_ALWAYS) {
+ ucontrol->value.integer.value[0] = 1;
+ } else if (msm8x16_wcd->boost_option == BYPASS_ALWAYS) {
+ ucontrol->value.integer.value[0] = 2;
+ } else if (msm8x16_wcd->boost_option == BOOST_ON_FOREVER) {
+ ucontrol->value.integer.value[0] = 3;
+ } else {
+ dev_err(codec->dev, "%s: ERROR: Unsupported Boost option= %d\n",
+ __func__, msm8x16_wcd->boost_option);
+ return -EINVAL;
+ }
+
+ dev_err(codec->dev, "%s: msm8x16_wcd->boost_option = %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ return 0;
+}
+
+static int msm8x16_wcd_boost_option_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 0:
+ msm8x16_wcd->boost_option = BOOST_SWITCH;
+ break;
+ case 1:
+ msm8x16_wcd->boost_option = BOOST_ALWAYS;
+ break;
+ case 2:
+ msm8x16_wcd->boost_option = BYPASS_ALWAYS;
+ msm8x16_wcd_bypass_on(codec);
+ break;
+ case 3:
+ msm8x16_wcd->boost_option = BOOST_ON_FOREVER;
+ msm8x16_wcd_boost_on(codec);
+ break;
+ default:
+ pr_err("%s: invalid boost option: %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ return -EINVAL;
+ }
+ dev_err(codec->dev, "%s: msm8x16_wcd->boost_option_set = %d\n",
+ __func__, msm8x16_wcd->boost_option);
+ return 0;
+}
+
+static int msm8x16_wcd_ext_spk_boost_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (msm8x16_wcd->ext_spk_boost_set == false)
+ ucontrol->value.integer.value[0] = 0;
+ else
+ ucontrol->value.integer.value[0] = 1;
+
+ dev_err(codec->dev, "%s: msm8x16_wcd->ext_spk_boost_set = %d\n",
+ __func__, msm8x16_wcd->ext_spk_boost_set);
+ return 0;
+}
+
+static int msm8x16_wcd_ext_spk_boost_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 0:
+ msm8x16_wcd->ext_spk_boost_set = false;
+ break;
+ case 1:
+ msm8x16_wcd->ext_spk_boost_set = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+ dev_err(codec->dev, "%s: msm8x16_wcd->spk_boost_set = %d\n",
+ __func__, msm8x16_wcd->spk_boost_set);
+ return 0;
+}
+static int msm8x16_wcd_get_iir_enable_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ ucontrol->value.integer.value[0] =
+ (snd_soc_read_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_CTL + 64 * iir_idx)) &
+ (1 << band_idx)) != 0;
+
+ dev_err(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
+ iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[0]);
+ return 0;
+}
+
+static int msm8x16_wcd_put_iir_enable_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+ int value = ucontrol->value.integer.value[0];
+
+ /* Mask first 5 bits, 6-8 are reserved */
+ snd_soc_update_bits_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_CTL + 64 * iir_idx),
+ (1 << band_idx), (value << band_idx));
+
+ dev_err(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
+ iir_idx, band_idx,
+ ((snd_soc_read_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_CTL + 64 * iir_idx)) &
+ (1 << band_idx)) != 0));
+
+ return 0;
+}
+static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
+ int iir_idx, int band_idx,
+ int coeff_idx)
+{
+ uint32_t value = 0;
+
+ /* Address does not automatically update if reading */
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL + 64 * iir_idx),
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t)) & 0x7F);
+
+ value |= snd_soc_read_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL + 64 * iir_idx));
+
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL + 64 * iir_idx),
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t) + 1) & 0x7F);
+
+ value |= (snd_soc_read_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 8);
+
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL + 64 * iir_idx),
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t) + 2) & 0x7F);
+
+ value |= (snd_soc_read_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 16);
+
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL + 64 * iir_idx),
+ ((band_idx * BAND_MAX + coeff_idx)
+ * sizeof(uint32_t) + 3) & 0x7F);
+
+ /* Mask bits top 2 bits since they are reserved */
+ value |= ((snd_soc_read_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL
+ + 64 * iir_idx)) & 0x3f) << 24);
+
+ return value;
+
+}
+
+static int msm8x16_wcd_get_iir_band_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ ucontrol->value.integer.value[0] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 0);
+ ucontrol->value.integer.value[1] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 1);
+ ucontrol->value.integer.value[2] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 2);
+ ucontrol->value.integer.value[3] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 3);
+ ucontrol->value.integer.value[4] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 4);
+
+ dev_err(codec->dev, "%s: IIR #%d band #%d b0 = 0x%x\n"
+ "%s: IIR #%d band #%d b1 = 0x%x\n"
+ "%s: IIR #%d band #%d b2 = 0x%x\n"
+ "%s: IIR #%d band #%d a1 = 0x%x\n"
+ "%s: IIR #%d band #%d a2 = 0x%x\n",
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[0],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[1],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[2],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[3],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[4]);
+ return 0;
+}
+
+static void set_iir_band_coeff(struct snd_soc_codec *codec,
+ int iir_idx, int band_idx,
+ uint32_t value)
+{
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL + 64 * iir_idx),
+ (value & 0xFF));
+
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL + 64 * iir_idx),
+ (value >> 8) & 0xFF);
+
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL + 64 * iir_idx),
+ (value >> 16) & 0xFF);
+
+ /* Mask top 2 bits, 7-8 are reserved */
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL + 64 * iir_idx),
+ (value >> 24) & 0x3F);
+
+}
+
+static int msm8x16_wcd_put_iir_band_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ /* Mask top bit it is reserved */
+ /* Updates addr automatically for each B2 write */
+ snd_soc_write_wrapper(codec,
+ (MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL + 64 * iir_idx),
+ (band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
+
+
+ set_iir_band_coeff(codec, iir_idx, band_idx,
+ ucontrol->value.integer.value[0]);
+ set_iir_band_coeff(codec, iir_idx, band_idx,
+ ucontrol->value.integer.value[1]);
+ set_iir_band_coeff(codec, iir_idx, band_idx,
+ ucontrol->value.integer.value[2]);
+ set_iir_band_coeff(codec, iir_idx, band_idx,
+ ucontrol->value.integer.value[3]);
+ set_iir_band_coeff(codec, iir_idx, band_idx,
+ ucontrol->value.integer.value[4]);
+
+ dev_err(codec->dev, "%s: IIR #%d band #%d b0 = 0x%x\n"
+ "%s: IIR #%d band #%d b1 = 0x%x\n"
+ "%s: IIR #%d band #%d b2 = 0x%x\n"
+ "%s: IIR #%d band #%d a1 = 0x%x\n"
+ "%s: IIR #%d band #%d a2 = 0x%x\n",
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 0),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 1),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 2),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 3),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 4));
+ return 0;
+}
+
+static int msm8x16_wcd_compander_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ int comp_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int rx_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ dev_err(codec->dev, "%s: msm8x16_wcd->comp[%d]_enabled[%d] = %d\n",
+ __func__, comp_idx, rx_idx,
+ msm8x16_wcd->comp_enabled[rx_idx]);
+
+ ucontrol->value.integer.value[0] = msm8x16_wcd->comp_enabled[rx_idx];
+
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ return 0;
+}
+
+static int msm8x16_wcd_compander_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ int comp_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int rx_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+ int value = ucontrol->value.integer.value[0];
+
+ dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ if (get_codec_version(msm8x16_wcd) >= DIANGU) {
+ if (!value)
+ msm8x16_wcd->comp_enabled[rx_idx] = 0;
+ else
+ msm8x16_wcd->comp_enabled[rx_idx] = comp_idx;
+ }
+
+ dev_err(codec->dev, "%s: msm8x16_wcd->comp[%d]_enabled[%d] = %d\n",
+ __func__, comp_idx, rx_idx,
+ msm8x16_wcd->comp_enabled[rx_idx]);
+
+ return 0;
+}
+
+static const char * const msm8x16_wcd_loopback_mode_ctrl_text[] = {
+ "DISABLE", "ENABLE"};
+static const struct soc_enum msm8x16_wcd_loopback_mode_ctl_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, msm8x16_wcd_loopback_mode_ctrl_text),
+};
+
+static const char * const msm8x16_wcd_ear_pa_boost_ctrl_text[] = {
+ "DISABLE", "ENABLE"};
+static const struct soc_enum msm8x16_wcd_ear_pa_boost_ctl_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, msm8x16_wcd_ear_pa_boost_ctrl_text),
+};
+
+static const char * const msm8x16_wcd_ear_pa_gain_text[] = {
+ "POS_1P5_DB", "POS_6_DB"};
+static const struct soc_enum msm8x16_wcd_ear_pa_gain_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, msm8x16_wcd_ear_pa_gain_text),
+};
+
+static const char * const msm8x16_wcd_boost_option_ctrl_text[] = {
+ "BOOST_SWITCH", "BOOST_ALWAYS", "BYPASS_ALWAYS",
+ "BOOST_ON_FOREVER"};
+static const struct soc_enum msm8x16_wcd_boost_option_ctl_enum[] = {
+ SOC_ENUM_SINGLE_EXT(4, msm8x16_wcd_boost_option_ctrl_text),
+};
+static const char * const msm8x16_wcd_spk_boost_ctrl_text[] = {
+ "DISABLE", "ENABLE"};
+static const struct soc_enum msm8x16_wcd_spk_boost_ctl_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, msm8x16_wcd_spk_boost_ctrl_text),
+};
+
+static const char * const msm8x16_wcd_ext_spk_boost_ctrl_text[] = {
+ "DISABLE", "ENABLE"};
+static const struct soc_enum msm8x16_wcd_ext_spk_boost_ctl_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, msm8x16_wcd_ext_spk_boost_ctrl_text),
+};
+
+static const char * const msm8x16_wcd_hph_mode_ctrl_text[] = {
+ "NORMAL", "HD2"};
+static const struct soc_enum msm8x16_wcd_hph_mode_ctl_enum[] = {
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(msm8x16_wcd_hph_mode_ctrl_text),
+ msm8x16_wcd_hph_mode_ctrl_text),
+};
+
+/*cut of frequency for high pass filter*/
+static const char * const cf_text[] = {
+ "MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
+};
+
+static const struct soc_enum cf_dec1_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_TX1_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec2_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_TX2_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_rxmix1_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_RX1_B4_CTL, 0, 3, cf_text);
+
+static const struct soc_enum cf_rxmix2_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_RX2_B4_CTL, 0, 3, cf_text);
+
+static const struct soc_enum cf_rxmix3_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_RX3_B4_CTL, 0, 3, cf_text);
+
+static const struct snd_kcontrol_new msm8x16_wcd_snd_controls[] = {
+
+ SOC_ENUM_EXT("RX HPH Mode", msm8x16_wcd_hph_mode_ctl_enum[0],
+ msm8x16_wcd_hph_mode_get, msm8x16_wcd_hph_mode_set),
+
+ SOC_ENUM_EXT("Boost Option", msm8x16_wcd_boost_option_ctl_enum[0],
+ msm8x16_wcd_boost_option_get, msm8x16_wcd_boost_option_set),
+
+ SOC_ENUM_EXT("EAR PA Boost", msm8x16_wcd_ear_pa_boost_ctl_enum[0],
+ msm8x16_wcd_ear_pa_boost_get, msm8x16_wcd_ear_pa_boost_set),
+
+ SOC_ENUM_EXT("EAR PA Gain", msm8x16_wcd_ear_pa_gain_enum[0],
+ msm8x16_wcd_pa_gain_get, msm8x16_wcd_pa_gain_put),
+
+ SOC_ENUM_EXT("Ext Spk Boost", msm8x16_wcd_ext_spk_boost_ctl_enum[0],
+ msm8x16_wcd_ext_spk_boost_get, msm8x16_wcd_ext_spk_boost_set),
+
+ SOC_ENUM_EXT("LOOPBACK Mode", msm8x16_wcd_loopback_mode_ctl_enum[0],
+ msm8x16_wcd_loopback_mode_get, msm8x16_wcd_loopback_mode_put),
+
+ SOC_SINGLE_TLV("ADC1 Volume", MSM89XX_PMIC_ANALOG_TX_1_EN, 3,
+ 8, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC2 Volume", MSM89XX_PMIC_ANALOG_TX_2_EN, 3,
+ 8, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC3 Volume", MSM89XX_PMIC_ANALOG_TX_3_EN, 3,
+ 8, 0, analog_gain),
+
+ SOC_SINGLE_SX_TLV("RX1 Digital Volume",
+ MSM89XX_CDC_CORE_RX1_VOL_CTL_B2_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("RX2 Digital Volume",
+ MSM89XX_CDC_CORE_RX2_VOL_CTL_B2_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("RX3 Digital Volume",
+ MSM89XX_CDC_CORE_RX3_VOL_CTL_B2_CTL,
+ 0, -84, 40, digital_gain),
+
+ SOC_SINGLE_SX_TLV("DEC1 Volume",
+ MSM89XX_CDC_CORE_TX1_VOL_CTL_GAIN,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("DEC2 Volume",
+ MSM89XX_CDC_CORE_TX2_VOL_CTL_GAIN,
+ 0, -84, 40, digital_gain),
+
+ SOC_SINGLE_SX_TLV("IIR1 INP1 Volume",
+ MSM89XX_CDC_CORE_IIR1_GAIN_B1_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("IIR1 INP2 Volume",
+ MSM89XX_CDC_CORE_IIR1_GAIN_B2_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("IIR1 INP3 Volume",
+ MSM89XX_CDC_CORE_IIR1_GAIN_B3_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("IIR1 INP4 Volume",
+ MSM89XX_CDC_CORE_IIR1_GAIN_B4_CTL,
+ 0, -84, 40, digital_gain),
+ SOC_SINGLE_SX_TLV("IIR2 INP1 Volume",
+ MSM89XX_CDC_CORE_IIR2_GAIN_B1_CTL,
+ 0, -84, 40, digital_gain),
+
+ SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
+ SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
+
+ SOC_SINGLE("TX1 HPF Switch",
+ MSM89XX_CDC_CORE_TX1_MUX_CTL, 3, 1, 0),
+ SOC_SINGLE("TX2 HPF Switch",
+ MSM89XX_CDC_CORE_TX2_MUX_CTL, 3, 1, 0),
+
+ SOC_SINGLE("RX1 HPF Switch",
+ MSM89XX_CDC_CORE_RX1_B5_CTL, 2, 1, 0),
+ SOC_SINGLE("RX2 HPF Switch",
+ MSM89XX_CDC_CORE_RX2_B5_CTL, 2, 1, 0),
+ SOC_SINGLE("RX3 HPF Switch",
+ MSM89XX_CDC_CORE_RX3_B5_CTL, 2, 1, 0),
+
+ SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum),
+ SOC_ENUM("RX2 HPF cut off", cf_rxmix2_enum),
+ SOC_ENUM("RX3 HPF cut off", cf_rxmix3_enum),
+
+ SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band1", IIR2, BAND1, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band2", IIR2, BAND2, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band3", IIR2, BAND3, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band4", IIR2, BAND4, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band5", IIR2, BAND5, 1, 0,
+ msm8x16_wcd_get_iir_enable_audio_mixer,
+ msm8x16_wcd_put_iir_enable_audio_mixer),
+
+ SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band1", IIR2, BAND1, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band2", IIR2, BAND2, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band3", IIR2, BAND3, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band4", IIR2, BAND4, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
+ msm8x16_wcd_get_iir_band_audio_mixer,
+ msm8x16_wcd_put_iir_band_audio_mixer),
+
+ SOC_SINGLE_EXT("COMP0 RX1", COMPANDER_1, MSM89XX_RX1, 1, 0,
+ msm8x16_wcd_compander_get, msm8x16_wcd_compander_set),
+
+ SOC_SINGLE_EXT("COMP0 RX2", COMPANDER_1, MSM89XX_RX2, 1, 0,
+ msm8x16_wcd_compander_get, msm8x16_wcd_compander_set),
+};
+
+static int tombak_hph_impedance_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ret;
+ uint32_t zl, zr;
+ bool hphr;
+ struct soc_multi_mixer_control *mc;
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ mc = (struct soc_multi_mixer_control *)(kcontrol->private_value);
+
+ hphr = mc->shift;
+ ret = wcd_mbhc_get_impedance(&priv->mbhc, &zl, &zr);
+ if (ret)
+ pr_err("%s: Failed to get mbhc imped", __func__);
+ pr_err("%s: zl %u, zr %u\n", __func__, zl, zr);
+ ucontrol->value.integer.value[0] = hphr ? zr : zl;
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new impedance_detect_controls[] = {
+ SOC_SINGLE_EXT("HPHL Impedance", 0, 0, UINT_MAX, 0,
+ tombak_hph_impedance_get, NULL),
+ SOC_SINGLE_EXT("HPHR Impedance", 0, 1, UINT_MAX, 0,
+ tombak_hph_impedance_get, NULL),
+};
+
+static int tombak_get_hph_type(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct msm8x16_wcd_priv *priv = snd_soc_codec_get_drvdata(codec);
+ struct wcd_mbhc *mbhc;
+
+ if (!priv) {
+ pr_err("%s: msm8x16-wcd private data is NULL\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ mbhc = &priv->mbhc;
+ if (!mbhc) {
+ pr_err("%s: mbhc not initialized\n", __func__);
+ return -EINVAL;
+ }
+
+ ucontrol->value.integer.value[0] = (u32) mbhc->hph_type;
+ pr_err("%s: hph_type = %u\n", __func__, mbhc->hph_type);
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new hph_type_detect_controls[] = {
+ SOC_SINGLE_EXT("HPH Type", 0, 0, UINT_MAX, 0,
+ tombak_get_hph_type, NULL),
+};
+
+static const char * const rx_mix1_text[] = {
+ "ZERO", "IIR1", "IIR2", "RX1", "RX2", "RX3"
+};
+
+static const char * const rx_mix2_text[] = {
+ "ZERO", "IIR1", "IIR2"
+};
+
+static const char * const dec_mux_text[] = {
+ "ZERO", "ADC1", "ADC2", "ADC3", "DMIC1", "DMIC2"
+};
+
+static const char * const dec3_mux_text[] = {
+ "ZERO", "DMIC3"
+};
+
+static const char * const dec4_mux_text[] = {
+ "ZERO", "DMIC4"
+};
+
+static const char * const adc2_mux_text[] = {
+ "ZERO", "INP2", "INP3"
+};
+
+static const char * const ext_spk_text[] = {
+ "Off", "On"
+};
+
+static const char * const wsa_spk_text[] = {
+ "ZERO", "WSA"
+};
+
+static const char * const rdac2_mux_text[] = {
+ "ZERO", "RX2", "RX1"
+};
+
+static const char * const iir_inp1_text[] = {
+ "ZERO", "DEC1", "DEC2", "RX1", "RX2", "RX3"
+};
+
+static const struct soc_enum adc2_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
+ ARRAY_SIZE(adc2_mux_text), adc2_mux_text);
+
+static const struct soc_enum ext_spk_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
+ ARRAY_SIZE(ext_spk_text), ext_spk_text);
+
+static const struct soc_enum wsa_spk_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
+ ARRAY_SIZE(wsa_spk_text), wsa_spk_text);
+
+/* RX1 MIX1 */
+static const struct soc_enum rx_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX1_B1_CTL,
+ 0, 6, rx_mix1_text);
+
+static const struct soc_enum rx_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX1_B1_CTL,
+ 3, 6, rx_mix1_text);
+
+static const struct soc_enum rx_mix1_inp3_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX1_B2_CTL,
+ 0, 6, rx_mix1_text);
+
+/* RX1 MIX2 */
+static const struct soc_enum rx_mix2_inp1_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX1_B3_CTL,
+ 0, 3, rx_mix2_text);
+
+/* RX2 MIX1 */
+static const struct soc_enum rx2_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX2_B1_CTL,
+ 0, 6, rx_mix1_text);
+
+static const struct soc_enum rx2_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX2_B1_CTL,
+ 3, 6, rx_mix1_text);
+
+static const struct soc_enum rx2_mix1_inp3_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX2_B1_CTL,
+ 0, 6, rx_mix1_text);
+
+/* RX2 MIX2 */
+static const struct soc_enum rx2_mix2_inp1_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX2_B3_CTL,
+ 0, 3, rx_mix2_text);
+
+/* RX3 MIX1 */
+static const struct soc_enum rx3_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX3_B1_CTL,
+ 0, 6, rx_mix1_text);
+
+static const struct soc_enum rx3_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX3_B1_CTL,
+ 3, 6, rx_mix1_text);
+
+static const struct soc_enum rx3_mix1_inp3_chain_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX3_B1_CTL,
+ 0, 6, rx_mix1_text);
+
+/* DEC */
+static const struct soc_enum dec1_mux_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_TX_B1_CTL,
+ 0, 6, dec_mux_text);
+
+static const struct soc_enum dec2_mux_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_TX_B1_CTL,
+ 3, 6, dec_mux_text);
+
+static const struct soc_enum dec3_mux_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_TX3_MUX_CTL, 0,
+ ARRAY_SIZE(dec3_mux_text), dec3_mux_text);
+
+static const struct soc_enum dec4_mux_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_TX4_MUX_CTL, 0,
+ ARRAY_SIZE(dec4_mux_text), dec4_mux_text);
+
+static const struct soc_enum rdac2_mux_enum =
+ SOC_ENUM_SINGLE(MSM89XX_PMIC_DIGITAL_CDC_CONN_HPHR_DAC_CTL,
+ 0, 3, rdac2_mux_text);
+
+static const struct soc_enum iir1_inp1_mux_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_EQ1_B1_CTL,
+ 0, 6, iir_inp1_text);
+
+static const struct soc_enum iir2_inp1_mux_enum =
+ SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_EQ2_B1_CTL,
+ 0, 6, iir_inp1_text);
+
+static const struct snd_kcontrol_new ext_spk_mux =
+ SOC_DAPM_ENUM("Ext Spk Switch Mux", ext_spk_enum);
+
+static const struct snd_kcontrol_new rx_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX1 MIX1 INP2 Mux", rx_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_mix1_inp3_mux =
+ SOC_DAPM_ENUM("RX1 MIX1 INP3 Mux", rx_mix1_inp3_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX2 MIX1 INP2 Mux", rx2_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix1_inp3_mux =
+ SOC_DAPM_ENUM("RX2 MIX1 INP3 Mux", rx2_mix1_inp3_chain_enum);
+
+static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx3_mix1_inp3_mux =
+ SOC_DAPM_ENUM("RX3 MIX1 INP3 Mux", rx3_mix1_inp3_chain_enum);
+
+static const struct snd_kcontrol_new rx1_mix2_inp1_mux =
+ SOC_DAPM_ENUM("RX1 MIX2 INP1 Mux", rx_mix2_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix2_inp1_mux =
+ SOC_DAPM_ENUM("RX2 MIX2 INP1 Mux", rx2_mix2_inp1_chain_enum);
+
+static const struct snd_kcontrol_new tx_adc2_mux =
+ SOC_DAPM_ENUM("ADC2 MUX Mux", adc2_enum);
+
+static int msm8x16_wcd_put_dec_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist =
+ dapm_kcontrol_get_wlist(kcontrol);
+ struct snd_soc_dapm_widget *w = wlist->widgets[0];
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ unsigned int dec_mux, decimator;
+ char *dec_name = NULL;
+ char *widget_name = NULL;
+ char *temp;
+ u16 tx_mux_ctl_reg;
+ u8 adc_dmic_sel = 0x0;
+ int ret = 0;
+ char *dec_num;
+
+ if (ucontrol->value.enumerated.item[0] > e->items) {
+ dev_err(codec->dev, "%s: Invalid enum value: %d\n",
+ __func__, ucontrol->value.enumerated.item[0]);
+ return -EINVAL;
+ }
+ dec_mux = ucontrol->value.enumerated.item[0];
+
+ widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+ if (!widget_name) {
+ dev_err(codec->dev, "%s: failed to copy string\n",
+ __func__);
+ return -ENOMEM;
+ }
+ temp = widget_name;
+
+ dec_name = strsep(&widget_name, " ");
+ widget_name = temp;
+ if (!dec_name) {
+ dev_err(codec->dev, "%s: Invalid decimator = %s\n",
+ __func__, w->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ dec_num = strpbrk(dec_name, "12");
+ if (dec_num == NULL) {
+ dev_err(codec->dev, "%s: Invalid DEC selected\n", __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = kstrtouint(dec_num, 10, &decimator);
+ if (ret < 0) {
+ dev_err(codec->dev, "%s: Invalid decimator = %s\n",
+ __func__, dec_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ dev_err(w->dapm->dev, "%s(): widget = %s decimator = %u dec_mux = %u\n"
+ , __func__, w->name, decimator, dec_mux);
+
+ switch (decimator) {
+ case 1:
+ case 2:
+ if ((dec_mux == 4) || (dec_mux == 5))
+ adc_dmic_sel = 0x1;
+ else
+ adc_dmic_sel = 0x0;
+ break;
+ default:
+ dev_err(codec->dev, "%s: Invalid Decimator = %u\n",
+ __func__, decimator);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ tx_mux_ctl_reg =
+ MSM89XX_CDC_CORE_TX1_MUX_CTL + 32 * (decimator - 1);
+
+ snd_soc_update_bits_wrapper(codec, tx_mux_ctl_reg, 0x1, adc_dmic_sel);
+
+ ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+
+out:
+ kfree(widget_name);
+ return ret;
+}
+
+#define MSM89XX_DEC_ENUM(xname, xenum) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = snd_soc_info_enum_double, \
+ .get = snd_soc_dapm_get_enum_double, \
+ .put = msm8x16_wcd_put_dec_enum, \
+ .private_value = (unsigned long)&xenum }
+
+static const struct snd_kcontrol_new dec1_mux =
+ MSM89XX_DEC_ENUM("DEC1 MUX Mux", dec1_mux_enum);
+
+static const struct snd_kcontrol_new dec2_mux =
+ MSM89XX_DEC_ENUM("DEC2 MUX Mux", dec2_mux_enum);
+
+static const struct snd_kcontrol_new dec3_mux =
+ SOC_DAPM_ENUM("DEC3 MUX Mux", dec3_mux_enum);
+
+static const struct snd_kcontrol_new dec4_mux =
+ SOC_DAPM_ENUM("DEC4 MUX Mux", dec4_mux_enum);
+
+static const struct snd_kcontrol_new rdac2_mux =
+ SOC_DAPM_ENUM("RDAC2 MUX Mux", rdac2_mux_enum);
+
+static const struct snd_kcontrol_new iir1_inp1_mux =
+ SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
+
+static const char * const ear_text[] = {
+ "ZERO", "Switch",
+};
+
+static const struct soc_enum ear_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(ear_text), ear_text);
+
+static const struct snd_kcontrol_new ear_pa_mux[] = {
+ SOC_DAPM_ENUM("EAR_S", ear_enum)
+};
+
+static const struct snd_kcontrol_new wsa_spk_mux[] = {
+ SOC_DAPM_ENUM("WSA Spk Switch", wsa_spk_enum)
+};
+
+static const struct snd_kcontrol_new iir2_inp1_mux =
+ SOC_DAPM_ENUM("IIR2 INP1 Mux", iir2_inp1_mux_enum);
+
+static const char * const hph_text[] = {
+ "ZERO", "Switch",
+};
+
+static const struct soc_enum hph_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hph_text), hph_text);
+
+static const struct snd_kcontrol_new hphl_mux[] = {
+ SOC_DAPM_ENUM("HPHL", hph_enum)
+};
+
+static const struct snd_kcontrol_new hphr_mux[] = {
+ SOC_DAPM_ENUM("HPHR", hph_enum)
+};
+
+static const struct snd_kcontrol_new spkr_mux[] = {
+ SOC_DAPM_ENUM("SPK", hph_enum)
+};
+
+static const char * const lo_text[] = {
+ "ZERO", "Switch",
+};
+
+static const struct soc_enum lo_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hph_text), hph_text);
+
+static const struct snd_kcontrol_new lo_mux[] = {
+ SOC_DAPM_ENUM("LINE_OUT", lo_enum)
+};
+
+static void msm8x16_wcd_codec_enable_adc_block(struct snd_soc_codec *codec,
+ int enable)
+{
+ struct msm8x16_wcd_priv *wcd8x16 = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s %d\n", __func__, enable);
+
+ if (enable) {
+ wcd8x16->adc_count++;
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL,
+ 0x20, 0x20);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x10, 0x10);
+ } else {
+ wcd8x16->adc_count--;
+ if (!wcd8x16->adc_count) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x10, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL,
+ 0x20, 0x0);
+ }
+ }
+}
+
+static int msm8x16_wcd_codec_enable_adc(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ u16 adc_reg;
+ u8 init_bit_shift;
+
+ dev_err(codec->dev, "%s %d\n", __func__, event);
+
+ adc_reg = MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_2;
+
+ if (w->reg == MSM89XX_PMIC_ANALOG_TX_1_EN)
+ init_bit_shift = 5;
+ else if ((w->reg == MSM89XX_PMIC_ANALOG_TX_2_EN) ||
+ (w->reg == MSM89XX_PMIC_ANALOG_TX_3_EN))
+ init_bit_shift = 4;
+ else {
+ dev_err(codec->dev, "%s: Error, invalid adc register\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ msm8x16_wcd_codec_enable_adc_block(codec, 1);
+ if (w->reg == MSM89XX_PMIC_ANALOG_TX_2_EN)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_CTL, 0x02, 0x02);
+ /*
+ * Add delay of 10 ms to give sufficient time for the voltage
+ * to shoot up and settle so that the txfe init does not
+ * happen when the input voltage is changing too much.
+ */
+ usleep_range(10000, 10010);
+ snd_soc_update_bits_wrapper(codec,
+ adc_reg, 1 << init_bit_shift,
+ 1 << init_bit_shift);
+ if (w->reg == MSM89XX_PMIC_ANALOG_TX_1_EN)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_CONN_TX1_CTL,
+ 0x03, 0x00);
+ else if ((w->reg == MSM89XX_PMIC_ANALOG_TX_2_EN) ||
+ (w->reg == MSM89XX_PMIC_ANALOG_TX_3_EN))
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_CONN_TX2_CTL,
+ 0x03, 0x00);
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ /*
+ * Add delay of 12 ms before deasserting the init
+ * to reduce the tx pop
+ */
+ usleep_range(12000, 12010);
+ snd_soc_update_bits_wrapper(codec,
+ adc_reg, 1 << init_bit_shift, 0x00);
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ msm8x16_wcd_codec_enable_adc_block(codec, 0);
+ if (w->reg == MSM89XX_PMIC_ANALOG_TX_2_EN)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_CTL, 0x02, 0x00);
+ if (w->reg == MSM89XX_PMIC_ANALOG_TX_1_EN)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_CONN_TX1_CTL,
+ 0x03, 0x02);
+ else if ((w->reg == MSM89XX_PMIC_ANALOG_TX_2_EN) ||
+ (w->reg == MSM89XX_PMIC_ANALOG_TX_3_EN))
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_CONN_TX2_CTL,
+ 0x03, 0x02);
+
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_spk_pa(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s %d %s\n", __func__, event, w->name);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL, 0x01, 0x01);
+ switch (msm8x16_wcd->boost_option) {
+ case BOOST_SWITCH:
+ if (!msm8x16_wcd->spk_boost_set)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL,
+ 0x10, 0x10);
+ break;
+ case BOOST_ALWAYS:
+ case BOOST_ON_FOREVER:
+ break;
+ case BYPASS_ALWAYS:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL,
+ 0x10, 0x10);
+ break;
+ default:
+ pr_err("%s: invalid boost option: %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ break;
+ }
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL, 0xE0, 0xE0);
+ if (get_codec_version(msm8x16_wcd) != TOMBAK_1_0)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL, 0x01, 0x01);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ switch (msm8x16_wcd->boost_option) {
+ case BOOST_SWITCH:
+ if (msm8x16_wcd->spk_boost_set)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
+ 0xEF, 0xEF);
+ else
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL,
+ 0x10, 0x00);
+ break;
+ case BOOST_ALWAYS:
+ case BOOST_ON_FOREVER:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
+ 0xEF, 0xEF);
+ break;
+ case BYPASS_ALWAYS:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x10, 0x00);
+ break;
+ default:
+ pr_err("%s: invalid boost option: %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ break;
+ }
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX3_B6_CTL, 0x01, 0x00);
+ snd_soc_update_bits_wrapper(codec, w->reg, 0x80, 0x80);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX3_B6_CTL, 0x01, 0x01);
+ msm8x16_wcd->mute_mask |= SPKR_PA_DISABLE;
+ /*
+ * Add 1 ms sleep for the mute to take effect
+ */
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x10, 0x10);
+ if (get_codec_version(msm8x16_wcd) < CAJON_2_0)
+ msm8x16_wcd_boost_mode_sequence(codec, SPK_PMD);
+ snd_soc_update_bits_wrapper(codec, w->reg, 0x80, 0x00);
+ switch (msm8x16_wcd->boost_option) {
+ case BOOST_SWITCH:
+ if (msm8x16_wcd->spk_boost_set)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
+ 0xEF, 0x69);
+ break;
+ case BOOST_ALWAYS:
+ case BOOST_ON_FOREVER:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
+ 0xEF, 0x69);
+ break;
+ case BYPASS_ALWAYS:
+ break;
+ default:
+ pr_err("%s: invalid boost option: %d\n", __func__,
+ msm8x16_wcd->boost_option);
+ break;
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL, 0xE0, 0x00);
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL, 0x01, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x10, 0x00);
+ if (get_codec_version(msm8x16_wcd) != TOMBAK_1_0)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL, 0x01, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x00);
+ if (get_codec_version(msm8x16_wcd) >= CAJON_2_0)
+ msm8x16_wcd_boost_mode_sequence(codec, SPK_PMD);
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_dig_clk(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ struct msm8916_asoc_mach_data *pdata = NULL;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+
+ dev_err(codec->dev, "%s event %d w->name %s\n", __func__,
+ event, w->name);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ msm8x16_wcd_codec_enable_clock_block(codec, 1);
+ snd_soc_update_bits_wrapper(codec, w->reg, 0x80, 0x80);
+ msm8x16_wcd_boost_mode_sequence(codec, SPK_PMU);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (msm8x16_wcd->rx_bias_count == 0)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x80, 0x00);
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_dmic(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ u8 dmic_clk_en;
+ u16 dmic_clk_reg;
+ s32 *dmic_clk_cnt;
+ unsigned int dmic;
+ int ret;
+ char *dec_num = strpbrk(w->name, "12");
+
+ if (dec_num == NULL) {
+ dev_err(codec->dev, "%s: Invalid DMIC\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = kstrtouint(dec_num, 10, &dmic);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "%s: Invalid DMIC line on the codec\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (dmic) {
+ case 1:
+ case 2:
+ dmic_clk_en = 0x01;
+ dmic_clk_cnt = &(msm8x16_wcd->dmic_1_2_clk_cnt);
+ dmic_clk_reg = MSM89XX_CDC_CORE_CLK_DMIC_B1_CTL;
+ dev_err(codec->dev,
+ "%s() event %d DMIC%d dmic_1_2_clk_cnt %d\n",
+ __func__, event, dmic, *dmic_clk_cnt);
+ break;
+ default:
+ dev_err(codec->dev, "%s: Invalid DMIC Selection\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ (*dmic_clk_cnt)++;
+ if (*dmic_clk_cnt == 1) {
+ snd_soc_update_bits_wrapper(codec, dmic_clk_reg,
+ 0x0E, 0x02);
+ snd_soc_update_bits_wrapper(codec, dmic_clk_reg,
+ dmic_clk_en, dmic_clk_en);
+ }
+ if (dmic == 1)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_TX1_DMIC_CTL, 0x07, 0x01);
+ if (dmic == 2)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_TX2_DMIC_CTL, 0x07, 0x01);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ (*dmic_clk_cnt)--;
+ if (*dmic_clk_cnt == 0)
+ snd_soc_update_bits_wrapper(codec, dmic_clk_reg,
+ dmic_clk_en, 0);
+ break;
+ }
+ return 0;
+}
+
+static bool msm8x16_wcd_use_mb(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (get_codec_version(msm8x16_wcd) < CAJON)
+ return true;
+ else
+ return false;
+}
+
+static void msm8x16_wcd_set_auto_zeroing(struct snd_soc_codec *codec,
+ bool enable)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (get_codec_version(msm8x16_wcd) < CONGA) {
+ if (enable)
+ /*
+ * Set autozeroing for special headset detection and
+ * buttons to work.
+ */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN,
+ 0x18, 0x10);
+ else
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN,
+ 0x18, 0x00);
+
+ } else {
+ pr_err("%s: Auto Zeroing is not required from CONGA\n",
+ __func__);
+ }
+}
+
+static void msm8x16_trim_btn_reg(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if (get_codec_version(msm8x16_wcd) == TOMBAK_1_0) {
+ pr_err("%s: This device needs to be trimmed\n", __func__);
+ /*
+ * Calculate the trim value for each device used
+ * till is comes in production by hardware team
+ */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SEC_ACCESS,
+ 0xA5, 0xA5);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_TRIM_CTRL2,
+ 0xFF, 0x30);
+ } else {
+ pr_err("%s: This device is trimmed at ATE\n", __func__);
+ }
+}
+static int msm8x16_wcd_enable_ext_mb_source(struct snd_soc_codec *codec,
+ bool turn_on)
+{
+ int ret = 0;
+ static int count;
+ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+
+ dev_err(codec->dev, "%s turn_on: %d count: %d\n", __func__, turn_on,
+ count);
+ if (turn_on) {
+ if (!count) {
+ ret = snd_soc_dapm_force_enable_pin(dapm,
+ "MICBIAS_REGULATOR");
+ snd_soc_dapm_sync(dapm);
+ }
+ count++;
+ } else {
+ if (count > 0)
+ count--;
+ if (!count) {
+ ret = snd_soc_dapm_disable_pin(dapm,
+ "MICBIAS_REGULATOR");
+ snd_soc_dapm_sync(dapm);
+ }
+ }
+
+ if (ret)
+ dev_err(codec->dev, "%s: Failed to %s external micbias source\n",
+ __func__, turn_on ? "enable" : "disabled");
+ else
+ dev_err(codec->dev, "%s: %s external micbias source\n",
+ __func__, turn_on ? "Enabled" : "Disabled");
+
+ return ret;
+}
+
+static int msm8x16_wcd_codec_enable_micbias(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd =
+ snd_soc_codec_get_drvdata(codec);
+ u16 micb_int_reg;
+ char *internal1_text = "Internal1";
+ char *internal2_text = "Internal2";
+ char *internal3_text = "Internal3";
+ char *external2_text = "External2";
+ char *external_text = "External";
+ bool micbias2;
+
+ dev_err(codec->dev, "%s %d\n", __func__, event);
+ switch (w->reg) {
+ case MSM89XX_PMIC_ANALOG_MICB_1_EN:
+ case MSM89XX_PMIC_ANALOG_MICB_2_EN:
+ micb_int_reg = MSM89XX_PMIC_ANALOG_MICB_1_INT_RBIAS;
+ break;
+ default:
+ dev_err(codec->dev,
+ "%s: Error, invalid micbias register 0x%x\n",
+ __func__, w->reg);
+ return -EINVAL;
+ }
+
+ micbias2 = (snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_2_EN) & 0x80);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (strnstr(w->name, internal1_text, strlen(w->name))) {
+ if (get_codec_version(msm8x16_wcd) >= CAJON)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL_2,
+ 0x02, 0x02);
+ snd_soc_update_bits_wrapper(codec,
+ micb_int_reg, 0x80, 0x80);
+ } else if (strnstr(w->name, internal2_text, strlen(w->name))) {
+ snd_soc_update_bits_wrapper(codec,
+ micb_int_reg, 0x10, 0x10);
+ snd_soc_update_bits_wrapper(codec,
+ w->reg, 0x60, 0x00);
+ } else if (strnstr(w->name, internal3_text, strlen(w->name))) {
+ snd_soc_update_bits_wrapper(codec,
+ micb_int_reg, 0x2, 0x2);
+ /*
+ * update MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL_2
+ * for external bias only, not for external2.
+ */
+ } else if (!strnstr(w->name, external2_text, strlen(w->name)) &&
+ strnstr(w->name, external_text,
+ strlen(w->name))) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL_2,
+ 0x02, 0x02);
+ }
+ if (!strnstr(w->name, external_text, strlen(w->name)))
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_EN, 0x05, 0x04);
+ if (w->reg == MSM89XX_PMIC_ANALOG_MICB_1_EN)
+ msm8x16_wcd_configure_cap(codec, true, micbias2);
+
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ if (get_codec_version(msm8x16_wcd) <= TOMBAK_2_0)
+ usleep_range(20000, 20100);
+ if (strnstr(w->name, internal1_text, strlen(w->name))) {
+ snd_soc_update_bits_wrapper(codec,
+ micb_int_reg, 0x40, 0x40);
+ } else if (strnstr(w->name, internal2_text, strlen(w->name))) {
+ snd_soc_update_bits_wrapper(codec,
+ micb_int_reg, 0x08, 0x08);
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_POST_MICBIAS_2_ON);
+ } else if (strnstr(w->name, internal3_text, 30)) {
+ snd_soc_update_bits_wrapper(codec,
+ micb_int_reg, 0x01, 0x01);
+ } else if (strnstr(w->name, external2_text, strlen(w->name))) {
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_POST_MICBIAS_2_ON);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (strnstr(w->name, internal1_text, strlen(w->name))) {
+ snd_soc_update_bits_wrapper(codec,
+ micb_int_reg, 0xC0, 0x40);
+ } else if (strnstr(w->name, internal2_text, strlen(w->name))) {
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_POST_MICBIAS_2_OFF);
+ } else if (strnstr(w->name, internal3_text, 30)) {
+ snd_soc_update_bits_wrapper(codec,
+ micb_int_reg, 0x2, 0x0);
+ } else if (strnstr(w->name, external2_text, strlen(w->name))) {
+ /*
+ * send micbias turn off event to mbhc driver and then
+ * break, as no need to set MICB_1_EN register.
+ */
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_POST_MICBIAS_2_OFF);
+ break;
+ }
+ if (w->reg == MSM89XX_PMIC_ANALOG_MICB_1_EN)
+ msm8x16_wcd_configure_cap(codec, false, micbias2);
+ break;
+ }
+ return 0;
+}
+
+static void tx_hpf_corner_freq_callback(struct work_struct *work)
+{
+ struct delayed_work *hpf_delayed_work;
+ struct hpf_work *hpf_work;
+ struct msm8x16_wcd_priv *msm8x16_wcd;
+ struct snd_soc_codec *codec;
+ u16 tx_mux_ctl_reg;
+ u8 hpf_cut_of_freq;
+
+ hpf_delayed_work = to_delayed_work(work);
+ hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+ msm8x16_wcd = hpf_work->msm8x16_wcd;
+ codec = hpf_work->msm8x16_wcd->codec;
+ hpf_cut_of_freq = hpf_work->tx_hpf_cut_of_freq;
+
+ tx_mux_ctl_reg = MSM89XX_CDC_CORE_TX1_MUX_CTL +
+ (hpf_work->decimator - 1) * 32;
+
+ dev_err(codec->dev, "%s(): decimator %u hpf_cut_of_freq 0x%x\n",
+ __func__, hpf_work->decimator, (unsigned int)hpf_cut_of_freq);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_TX_1_2_TXFE_CLKDIV, 0xFF, 0x51);
+
+ snd_soc_update_bits_wrapper(codec,
+ tx_mux_ctl_reg, 0x30, hpf_cut_of_freq << 4);
+}
+
+
+#define TX_MUX_CTL_CUT_OFF_FREQ_MASK 0x30
+#define CF_MIN_3DB_4HZ 0x0
+#define CF_MIN_3DB_75HZ 0x1
+#define CF_MIN_3DB_150HZ 0x2
+
+static int msm8x16_wcd_codec_set_iir_gain(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ int value = 0, reg;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ if (w->shift == 0)
+ reg = MSM89XX_CDC_CORE_IIR1_GAIN_B1_CTL;
+ else if (w->shift == 1)
+ reg = MSM89XX_CDC_CORE_IIR2_GAIN_B1_CTL;
+ value = snd_soc_read_wrapper(codec, reg);
+ snd_soc_write_wrapper(codec, reg, value);
+ break;
+ default:
+ pr_err("%s: event = %d not expected\n", __func__, event);
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_dec(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8916_asoc_mach_data *pdata = NULL;
+ unsigned int decimator;
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ char *dec_name = NULL;
+ char *widget_name = NULL;
+ char *temp;
+ int ret = 0, i;
+ u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
+ u8 dec_hpf_cut_of_freq;
+ int offset;
+ char *dec_num;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ dev_err(codec->dev, "%s %d\n", __func__, event);
+
+ widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+ if (!widget_name)
+ return -ENOMEM;
+ temp = widget_name;
+
+ dec_name = strsep(&widget_name, " ");
+ widget_name = temp;
+ if (!dec_name) {
+ dev_err(codec->dev,
+ "%s: Invalid decimator = %s\n", __func__, w->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ dec_num = strpbrk(dec_name, "1234");
+ if (dec_num == NULL) {
+ dev_err(codec->dev, "%s: Invalid Decimator\n", __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = kstrtouint(dec_num, 10, &decimator);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "%s: Invalid decimator = %s\n", __func__, dec_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ dev_err(codec->dev,
+ "%s(): widget = %s dec_name = %s decimator = %u\n", __func__,
+ w->name, dec_name, decimator);
+
+ if (w->reg == MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL) {
+ dec_reset_reg = MSM89XX_CDC_CORE_CLK_TX_RESET_B1_CTL;
+ offset = 0;
+ } else {
+ dev_err(codec->dev, "%s: Error, incorrect dec\n", __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ tx_vol_ctl_reg = MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG +
+ 32 * (decimator - 1);
+ tx_mux_ctl_reg = MSM89XX_CDC_CORE_TX1_MUX_CTL +
+ 32 * (decimator - 1);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (decimator == 3 || decimator == 4) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_WSA_VI_B1_CTL,
+ 0xFF, 0x5);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_TX1_DMIC_CTL +
+ (decimator - 1) * 0x20, 0x7, 0x2);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_TX1_DMIC_CTL +
+ (decimator - 1) * 0x20, 0x7, 0x2);
+ }
+ /* Enableable TX digital mute */
+ snd_soc_update_bits_wrapper(codec, tx_vol_ctl_reg, 0x01, 0x01);
+ for (i = 0; i < NUM_DECIMATORS; i++) {
+ if (decimator == i + 1)
+ msm8x16_wcd->dec_active[i] = true;
+ }
+
+ dec_hpf_cut_of_freq =
+ snd_soc_read_wrapper(codec, tx_mux_ctl_reg);
+
+ dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq & 0x30) >> 4;
+
+ tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq =
+ dec_hpf_cut_of_freq;
+
+ if (dec_hpf_cut_of_freq != CF_MIN_3DB_150HZ) {
+
+ /* set cut of freq to CF_MIN_3DB_150HZ (0x1); */
+ snd_soc_update_bits_wrapper(codec, tx_mux_ctl_reg, 0x30,
+ CF_MIN_3DB_150HZ << 4);
+ }
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_TX_1_2_TXFE_CLKDIV,
+ 0xFF, 0x42);
+
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ /* enable HPF */
+ snd_soc_update_bits_wrapper(codec, tx_mux_ctl_reg, 0x08, 0x00);
+
+ if (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
+ CF_MIN_3DB_150HZ) {
+
+ schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
+ msecs_to_jiffies(300));
+ }
+ /* apply the digital gain after the decimator is enabled*/
+ if ((w->shift) < ARRAY_SIZE(tx_digital_gain_reg))
+ snd_soc_write_wrapper(codec,
+ tx_digital_gain_reg[w->shift + offset],
+ snd_soc_read_wrapper(codec,
+ tx_digital_gain_reg[w->shift + offset])
+ );
+ if (pdata->lb_mode) {
+ pr_err("%s: loopback mode unmute the DEC\n",
+ __func__);
+ snd_soc_update_bits_wrapper(codec,
+ tx_vol_ctl_reg, 0x01, 0x00);
+ }
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits_wrapper(codec, tx_vol_ctl_reg, 0x01, 0x01);
+ msleep(20);
+ snd_soc_update_bits_wrapper(codec, tx_mux_ctl_reg, 0x08, 0x08);
+ cancel_delayed_work_sync(&tx_hpf_work[decimator - 1].dwork);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits_wrapper(codec,
+ dec_reset_reg, 1 << w->shift, 1 << w->shift);
+ snd_soc_update_bits_wrapper(codec,
+ dec_reset_reg, 1 << w->shift, 0x0);
+ snd_soc_update_bits_wrapper(codec,
+ tx_mux_ctl_reg, 0x08, 0x08);
+ snd_soc_update_bits_wrapper(codec,
+ tx_mux_ctl_reg, 0x30,
+ (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq) << 4);
+ snd_soc_update_bits_wrapper(codec,
+ tx_vol_ctl_reg, 0x01, 0x00);
+ for (i = 0; i < NUM_DECIMATORS; i++) {
+ if (decimator == i + 1)
+ msm8x16_wcd->dec_active[i] = false;
+ }
+ if (decimator == 3 || decimator == 4) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_WSA_VI_B1_CTL,
+ 0xFF, 0x0);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_TX1_DMIC_CTL +
+ (decimator - 1) * 0x20, 0x7, 0x0);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_TX1_DMIC_CTL +
+ (decimator - 1) * 0x20, 0x7, 0x0);
+ }
+ break;
+ }
+out:
+ kfree(widget_name);
+ return ret;
+}
+
+static int msm89xx_wcd_codec_enable_vdd_spkr(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+
+ if (!msm8x16_wcd->ext_spk_boost_set) {
+ dev_err(codec->dev, "%s: ext_boost not supported/disabled\n",
+ __func__);
+ return 0;
+ }
+ dev_err(codec->dev, "%s: %s %d\n", __func__, w->name, event);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (msm8x16_wcd->spkdrv_reg) {
+ ret = regulator_enable(msm8x16_wcd->spkdrv_reg);
+ if (ret)
+ dev_err(codec->dev,
+ "%s Failed to enable spkdrv reg %s\n",
+ __func__, MSM89XX_VDD_SPKDRV_NAME);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (msm8x16_wcd->spkdrv_reg) {
+ ret = regulator_disable(msm8x16_wcd->spkdrv_reg);
+ if (ret)
+ dev_err(codec->dev,
+ "%s: Failed to disable spkdrv_reg %s\n",
+ __func__, MSM89XX_VDD_SPKDRV_NAME);
+ }
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_config_compander(struct snd_soc_codec *codec,
+ int interp_n, int event)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: event %d shift %d, enabled %d\n",
+ __func__, event, interp_n,
+ msm8x16_wcd->comp_enabled[interp_n]);
+
+ /* compander is not enabled */
+ if (!msm8x16_wcd->comp_enabled[interp_n])
+ return 0;
+
+ switch (msm8x16_wcd->comp_enabled[interp_n]) {
+ case COMPANDER_1:
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ /* Enable Compander Clock */
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_COMP0_B2_CTL, 0x0F, 0x09);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_RX_B2_CTL, 0x01, 0x01);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_COMP0_B1_CTL,
+ 1 << interp_n, 1 << interp_n);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_COMP0_B3_CTL, 0xFF, 0x01);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_COMP0_B2_CTL, 0xF0, 0x50);
+ /* add sleep for compander to settle */
+ usleep_range(1000, 1100);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_COMP0_B3_CTL, 0xFF, 0x28);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_COMP0_B2_CTL, 0xF0, 0xB0);
+
+ /* Enable Compander GPIO */
+ if (msm8x16_wcd->codec_hph_comp_gpio)
+ msm8x16_wcd->codec_hph_comp_gpio(1);
+ } else if (SND_SOC_DAPM_EVENT_OFF(event)) {
+ /* Disable Compander GPIO */
+ if (msm8x16_wcd->codec_hph_comp_gpio)
+ msm8x16_wcd->codec_hph_comp_gpio(0);
+
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_COMP0_B2_CTL, 0x0F, 0x05);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_COMP0_B1_CTL,
+ 1 << interp_n, 0);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_RX_B2_CTL, 0x01, 0x00);
+ }
+ break;
+ default:
+ dev_err(codec->dev, "%s: Invalid compander %d\n", __func__,
+ msm8x16_wcd->comp_enabled[interp_n]);
+ break;
+ };
+
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s %d %s\n", __func__, event, w->name);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ msm8x16_wcd_codec_config_compander(codec, w->shift, event);
+ /* apply the digital gain after the interpolator is enabled*/
+ if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
+ snd_soc_write_wrapper(codec,
+ rx_digital_gain_reg[w->shift],
+ snd_soc_read_wrapper(codec,
+ rx_digital_gain_reg[w->shift])
+ );
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ msm8x16_wcd_codec_config_compander(codec, w->shift, event);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_RX_RESET_CTL,
+ 1 << w->shift, 1 << w->shift);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_RX_RESET_CTL,
+ 1 << w->shift, 0x0);
+ /*
+ * disable the mute enabled during the PMD of this device
+ */
+ if ((w->shift == 0) &&
+ (msm8x16_wcd->mute_mask & HPHL_PA_DISABLE)) {
+ pr_err("disabling HPHL mute\n");
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B6_CTL, 0x01, 0x00);
+ if (get_codec_version(msm8x16_wcd) >= CAJON)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_CNP,
+ 0xF0, 0x20);
+ msm8x16_wcd->mute_mask &= ~(HPHL_PA_DISABLE);
+ } else if ((w->shift == 1) &&
+ (msm8x16_wcd->mute_mask & HPHR_PA_DISABLE)) {
+ pr_err("disabling HPHR mute\n");
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B6_CTL, 0x01, 0x00);
+ if (get_codec_version(msm8x16_wcd) >= CAJON)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_CNP,
+ 0xF0, 0x20);
+ msm8x16_wcd->mute_mask &= ~(HPHR_PA_DISABLE);
+ } else if ((w->shift == 2) &&
+ (msm8x16_wcd->mute_mask & SPKR_PA_DISABLE)) {
+ pr_err("disabling SPKR mute\n");
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX3_B6_CTL, 0x01, 0x00);
+ msm8x16_wcd->mute_mask &= ~(SPKR_PA_DISABLE);
+ } else if ((w->shift == 0) &&
+ (msm8x16_wcd->mute_mask & EAR_PA_DISABLE)) {
+ pr_err("disabling EAR mute\n");
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B6_CTL, 0x01, 0x00);
+ msm8x16_wcd->mute_mask &= ~(EAR_PA_DISABLE);
+ }
+ }
+ return 0;
+}
+
+
+/* The register address is the same as other codec so it can use resmgr */
+static int msm8x16_wcd_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ msm8x16_wcd->rx_bias_count++;
+ if (msm8x16_wcd->rx_bias_count == 1) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC,
+ 0x80, 0x80);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC,
+ 0x01, 0x01);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ msm8x16_wcd->rx_bias_count--;
+ if (msm8x16_wcd->rx_bias_count == 0) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC,
+ 0x01, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC,
+ 0x80, 0x00);
+ }
+ break;
+ }
+ dev_err(codec->dev, "%s rx_bias_count = %d\n",
+ __func__, msm8x16_wcd->rx_bias_count);
+ return 0;
+}
+
+static uint32_t wcd_get_impedance_value(uint32_t imped)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(wcd_imped_val) - 1; i++) {
+ if (imped >= wcd_imped_val[i] &&
+ imped < wcd_imped_val[i + 1])
+ break;
+ }
+
+ pr_err("%s: selected impedance value = %d\n",
+ __func__, wcd_imped_val[i]);
+ return wcd_imped_val[i];
+}
+
+void wcd_imped_config(struct snd_soc_codec *codec,
+ uint32_t imped, bool set_gain)
+{
+ uint32_t value;
+ int codec_version;
+ struct msm8x16_wcd_priv *msm8x16_wcd =
+ snd_soc_codec_get_drvdata(codec);
+
+ value = wcd_get_impedance_value(imped);
+
+ if (value < wcd_imped_val[0]) {
+ pr_err("%s, detected impedance is less than 4 Ohm\n",
+ __func__);
+ return;
+ }
+ if (value >= wcd_imped_val[ARRAY_SIZE(wcd_imped_val) - 1]) {
+ pr_err("%s, invalid imped, greater than 48 Ohm\n = %d\n",
+ __func__, value);
+ return;
+ }
+
+ codec_version = get_codec_version(msm8x16_wcd);
+
+ if (set_gain) {
+ switch (codec_version) {
+ case TOMBAK_1_0:
+ case TOMBAK_2_0:
+ case CONGA:
+ /*
+ * For 32Ohm load and higher loads, Set 0x19E
+ * bit 5 to 1 (POS_6_DB_DI). For loads lower
+ * than 32Ohm (such as 16Ohm load), Set 0x19E
+ * bit 5 to 0 (POS_1P5_DB_DI)
+ */
+ if (value >= 32)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL,
+ 0x20, 0x20);
+ else
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL,
+ 0x20, 0x00);
+ break;
+ case CAJON:
+ case CAJON_2_0:
+ case DIANGU:
+ if (value >= 13) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL,
+ 0x20, 0x20);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_NCP_VCTRL,
+ 0x07, 0x07);
+ } else {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL,
+ 0x20, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_NCP_VCTRL,
+ 0x07, 0x04);
+ }
+ break;
+ }
+ } else {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL,
+ 0x20, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_NCP_VCTRL,
+ 0x07, 0x04);
+ }
+
+ pr_err("%s: Exit\n", __func__);
+}
+
+static int msm8x16_wcd_hphl_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ uint32_t impedl, impedr;
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ dev_err(codec->dev, "%s %s %d\n", __func__, w->name, event);
+ ret = wcd_mbhc_get_impedance(&msm8x16_wcd->mbhc,
+ &impedl, &impedr);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (get_codec_version(msm8x16_wcd) > CAJON)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN,
+ 0x08, 0x08);
+ if (get_codec_version(msm8x16_wcd) == CAJON ||
+ get_codec_version(msm8x16_wcd) == CAJON_2_0) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_L_TEST,
+ 0x80, 0x80);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_R_TEST,
+ 0x80, 0x80);
+ }
+ if (get_codec_version(msm8x16_wcd) > CAJON)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN,
+ 0x08, 0x00);
+ if (msm8x16_wcd->hph_mode == HD2_MODE) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B3_CTL, 0x1C, 0x14);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B4_CTL, 0x18, 0x10);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B3_CTL, 0x80, 0x80);
+ }
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_L_PA_DAC_CTL, 0x02, 0x02);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL, 0x01, 0x01);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x02, 0x02);
+ if (!ret)
+ wcd_imped_config(codec, impedl, true);
+ else
+ dev_err(codec->dev, "Failed to get mbhc impedance %d\n",
+ ret);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_L_PA_DAC_CTL, 0x02, 0x00);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ wcd_imped_config(codec, impedl, false);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x02, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL, 0x01, 0x00);
+ if (msm8x16_wcd->hph_mode == HD2_MODE) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B3_CTL, 0x1C, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B4_CTL, 0x18, 0xFF);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B3_CTL, 0x80, 0x00);
+ }
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_lo_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ dev_err(codec->dev, "%s %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL, 0x20, 0x20);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL, 0x80, 0x80);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL, 0x08, 0x08);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL, 0x40, 0x40);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL, 0x80, 0x80);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL, 0x08, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL, 0x40, 0x40);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ usleep_range(20000, 20100);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL, 0x80, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL, 0x40, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL, 0x08, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL, 0x80, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL, 0x40, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL, 0x20, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x00);
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_hphr_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (msm8x16_wcd->hph_mode == HD2_MODE) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B3_CTL, 0x1C, 0x14);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B4_CTL, 0x18, 0x10);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B3_CTL, 0x80, 0x80);
+ }
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_R_PA_DAC_CTL, 0x02, 0x02);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL, 0x02, 0x02);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x01, 0x01);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_R_PA_DAC_CTL, 0x02, 0x00);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL, 0x01, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL, 0x02, 0x00);
+ if (msm8x16_wcd->hph_mode == HD2_MODE) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B3_CTL, 0x1C, 0x00);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B4_CTL, 0x18, 0xFF);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B3_CTL, 0x80, 0x00);
+ }
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_hph_pa_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: %s event = %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (w->shift == 5)
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_PRE_HPHL_PA_ON);
+ else if (w->shift == 4)
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_PRE_HPHR_PA_ON);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_NCP_FBCTRL, 0x20, 0x20);
+ break;
+
+ case SND_SOC_DAPM_POST_PMU:
+ usleep_range(7000, 7100);
+ if (w->shift == 5) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_L_TEST, 0x04, 0x04);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B6_CTL, 0x01, 0x00);
+ } else if (w->shift == 4) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_R_TEST, 0x04, 0x04);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B6_CTL, 0x01, 0x00);
+ }
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ if (w->shift == 5) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B6_CTL, 0x01, 0x01);
+ msleep(20);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_L_TEST, 0x04, 0x00);
+ msm8x16_wcd->mute_mask |= HPHL_PA_DISABLE;
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_PRE_HPHL_PA_OFF);
+ } else if (w->shift == 4) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX2_B6_CTL, 0x01, 0x01);
+ msleep(20);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_R_TEST, 0x04, 0x00);
+ msm8x16_wcd->mute_mask |= HPHR_PA_DISABLE;
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_PRE_HPHR_PA_OFF);
+ }
+ if (get_codec_version(msm8x16_wcd) >= CAJON) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_CNP,
+ 0xF0, 0x30);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (w->shift == 5) {
+ clear_bit(WCD_MBHC_HPHL_PA_OFF_ACK,
+ &msm8x16_wcd->mbhc.hph_pa_dac_state);
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_POST_HPHL_PA_OFF);
+ } else if (w->shift == 4) {
+ clear_bit(WCD_MBHC_HPHR_PA_OFF_ACK,
+ &msm8x16_wcd->mbhc.hph_pa_dac_state);
+ msm8x16_notifier_call(codec,
+ WCD_EVENT_POST_HPHR_PA_OFF);
+ }
+ usleep_range(4000, 4100);
+ usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
+
+ dev_err(codec->dev,
+ "%s: sleep 10 ms after %s PA disable.\n", __func__,
+ w->name);
+ usleep_range(10000, 10100);
+ break;
+ }
+ return 0;
+}
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ {"RX_I2S_CLK", NULL, "CDC_CONN"},
+ {"I2S RX1", NULL, "RX_I2S_CLK"},
+ {"I2S RX2", NULL, "RX_I2S_CLK"},
+ {"I2S RX3", NULL, "RX_I2S_CLK"},
+
+ {"I2S TX1", NULL, "TX_I2S_CLK"},
+ {"I2S TX2", NULL, "TX_I2S_CLK"},
+ {"AIF2 VI", NULL, "TX_I2S_CLK"},
+
+ {"I2S TX1", NULL, "DEC1 MUX"},
+ {"I2S TX2", NULL, "DEC2 MUX"},
+ {"AIF2 VI", NULL, "DEC3 MUX"},
+ {"AIF2 VI", NULL, "DEC4 MUX"},
+
+ /* RDAC Connections */
+ {"HPHR DAC", NULL, "RDAC2 MUX"},
+ {"RDAC2 MUX", "RX1", "RX1 CHAIN"},
+ {"RDAC2 MUX", "RX2", "RX2 CHAIN"},
+
+ /* WSA */
+ {"WSA_SPK OUT", NULL, "WSA Spk Switch"},
+ {"WSA Spk Switch", "WSA", "EAR PA"},
+
+ /* Earpiece (RX MIX1) */
+ {"EAR", NULL, "EAR_S"},
+ {"EAR_S", "Switch", "EAR PA"},
+ {"EAR PA", NULL, "RX_BIAS"},
+ {"EAR PA", NULL, "HPHL DAC"},
+ {"EAR PA", NULL, "HPHR DAC"},
+ {"EAR PA", NULL, "EAR CP"},
+
+ /* Headset (RX MIX1 and RX MIX2) */
+ {"HEADPHONE", NULL, "HPHL PA"},
+ {"HEADPHONE", NULL, "HPHR PA"},
+
+ {"Ext Spk", NULL, "Ext Spk Switch"},
+ {"Ext Spk Switch", "On", "HPHL PA"},
+ {"Ext Spk Switch", "On", "HPHR PA"},
+
+ {"HPHL PA", NULL, "HPHL"},
+ {"HPHR PA", NULL, "HPHR"},
+ {"HPHL", "Switch", "HPHL DAC"},
+ {"HPHR", "Switch", "HPHR DAC"},
+ {"HPHL PA", NULL, "CP"},
+ {"HPHL PA", NULL, "RX_BIAS"},
+ {"HPHR PA", NULL, "CP"},
+ {"HPHR PA", NULL, "RX_BIAS"},
+ {"HPHL DAC", NULL, "RX1 CHAIN"},
+
+ {"SPK_OUT", NULL, "SPK PA"},
+ {"SPK PA", NULL, "SPK_RX_BIAS"},
+ {"SPK PA", NULL, "SPK"},
+ {"SPK", "Switch", "SPK DAC"},
+ {"SPK DAC", NULL, "RX3 CHAIN"},
+ {"SPK DAC", NULL, "VDD_SPKDRV"},
+
+ /* lineout */
+ {"LINEOUT", NULL, "LINEOUT PA"},
+ {"LINEOUT PA", NULL, "SPK_RX_BIAS"},
+ {"LINEOUT PA", NULL, "LINE_OUT"},
+ {"LINE_OUT", "Switch", "LINEOUT DAC"},
+ {"LINEOUT DAC", NULL, "RX3 CHAIN"},
+
+ /* lineout to WSA */
+ {"WSA_SPK OUT", NULL, "LINEOUT PA"},
+
+ {"RX1 CHAIN", NULL, "RX1 CLK"},
+ {"RX2 CHAIN", NULL, "RX2 CLK"},
+ {"RX3 CHAIN", NULL, "RX3 CLK"},
+ {"RX1 CHAIN", NULL, "RX1 MIX2"},
+ {"RX2 CHAIN", NULL, "RX2 MIX2"},
+ {"RX3 CHAIN", NULL, "RX3 MIX1"},
+
+ {"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
+ {"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
+ {"RX1 MIX1", NULL, "RX1 MIX1 INP3"},
+ {"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
+ {"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
+ {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
+ {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
+ {"RX1 MIX2", NULL, "RX1 MIX1"},
+ {"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
+ {"RX2 MIX2", NULL, "RX2 MIX1"},
+ {"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
+
+ {"RX1 MIX1 INP1", "RX1", "I2S RX1"},
+ {"RX1 MIX1 INP1", "RX2", "I2S RX2"},
+ {"RX1 MIX1 INP1", "RX3", "I2S RX3"},
+ {"RX1 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX1 MIX1 INP1", "IIR2", "IIR2"},
+ {"RX1 MIX1 INP2", "RX1", "I2S RX1"},
+ {"RX1 MIX1 INP2", "RX2", "I2S RX2"},
+ {"RX1 MIX1 INP2", "RX3", "I2S RX3"},
+ {"RX1 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX1 MIX1 INP2", "IIR2", "IIR2"},
+ {"RX1 MIX1 INP3", "RX1", "I2S RX1"},
+ {"RX1 MIX1 INP3", "RX2", "I2S RX2"},
+ {"RX1 MIX1 INP3", "RX3", "I2S RX3"},
+
+ {"RX2 MIX1 INP1", "RX1", "I2S RX1"},
+ {"RX2 MIX1 INP1", "RX2", "I2S RX2"},
+ {"RX2 MIX1 INP1", "RX3", "I2S RX3"},
+ {"RX2 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX2 MIX1 INP1", "IIR2", "IIR2"},
+ {"RX2 MIX1 INP2", "RX1", "I2S RX1"},
+ {"RX2 MIX1 INP2", "RX2", "I2S RX2"},
+ {"RX2 MIX1 INP2", "RX3", "I2S RX3"},
+ {"RX2 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX2 MIX1 INP2", "IIR2", "IIR2"},
+
+ {"RX3 MIX1 INP1", "RX1", "I2S RX1"},
+ {"RX3 MIX1 INP1", "RX2", "I2S RX2"},
+ {"RX3 MIX1 INP1", "RX3", "I2S RX3"},
+ {"RX3 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX3 MIX1 INP1", "IIR2", "IIR2"},
+ {"RX3 MIX1 INP2", "RX1", "I2S RX1"},
+ {"RX3 MIX1 INP2", "RX2", "I2S RX2"},
+ {"RX3 MIX1 INP2", "RX3", "I2S RX3"},
+ {"RX3 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX3 MIX1 INP2", "IIR2", "IIR2"},
+
+ {"RX1 MIX2 INP1", "IIR1", "IIR1"},
+ {"RX2 MIX2 INP1", "IIR1", "IIR1"},
+ {"RX1 MIX2 INP1", "IIR2", "IIR2"},
+ {"RX2 MIX2 INP1", "IIR2", "IIR2"},
+
+ /* Decimator Inputs */
+ {"DEC1 MUX", "DMIC1", "DMIC1"},
+ {"DEC1 MUX", "DMIC2", "DMIC2"},
+ {"DEC1 MUX", "ADC1", "ADC1"},
+ {"DEC1 MUX", "ADC2", "ADC2"},
+ {"DEC1 MUX", "ADC3", "ADC3"},
+ {"DEC1 MUX", NULL, "CDC_CONN"},
+
+ {"DEC2 MUX", "DMIC1", "DMIC1"},
+ {"DEC2 MUX", "DMIC2", "DMIC2"},
+ {"DEC2 MUX", "ADC1", "ADC1"},
+ {"DEC2 MUX", "ADC2", "ADC2"},
+ {"DEC2 MUX", "ADC3", "ADC3"},
+ {"DEC2 MUX", NULL, "CDC_CONN"},
+
+ {"DEC3 MUX", "DMIC3", "DMIC3"},
+ {"DEC4 MUX", "DMIC4", "DMIC4"},
+ {"DEC3 MUX", NULL, "CDC_CONN"},
+ {"DEC4 MUX", NULL, "CDC_CONN"},
+ /* ADC Connections */
+ {"ADC2", NULL, "ADC2 MUX"},
+ {"ADC3", NULL, "ADC2 MUX"},
+ {"ADC2 MUX", "INP2", "ADC2_INP2"},
+ {"ADC2 MUX", "INP3", "ADC2_INP3"},
+
+ {"ADC1", NULL, "AMIC1"},
+ {"ADC2_INP2", NULL, "AMIC2"},
+ {"ADC2_INP3", NULL, "AMIC3"},
+
+ /* TODO: Fix this */
+ {"IIR1", NULL, "IIR1 INP1 MUX"},
+ {"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
+ {"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
+ {"IIR2", NULL, "IIR2 INP1 MUX"},
+ {"IIR2 INP1 MUX", "DEC1", "DEC1 MUX"},
+ {"IIR2 INP1 MUX", "DEC2", "DEC2 MUX"},
+ {"MIC BIAS Internal1", NULL, "INT_LDO_H"},
+ {"MIC BIAS Internal2", NULL, "INT_LDO_H"},
+ {"MIC BIAS External", NULL, "INT_LDO_H"},
+ {"MIC BIAS External2", NULL, "INT_LDO_H"},
+ {"MIC BIAS Internal1", NULL, "MICBIAS_REGULATOR"},
+ {"MIC BIAS Internal2", NULL, "MICBIAS_REGULATOR"},
+ {"MIC BIAS External", NULL, "MICBIAS_REGULATOR"},
+ {"MIC BIAS External2", NULL, "MICBIAS_REGULATOR"},
+};
+
+static int msm8x16_wcd_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd =
+ snd_soc_codec_get_drvdata(dai->codec);
+
+ dev_err(dai->codec->dev, "%s(): substream = %s stream = %d\n",
+ __func__,
+ substream->name, substream->stream);
+ /*
+ * If status_mask is BU_DOWN it means SSR is not complete.
+ * So retun error.
+ */
+ if (test_bit(BUS_DOWN, &msm8x16_wcd->status_mask)) {
+ dev_err(dai->codec->dev, "Error, Device is not up post SSR\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void msm8x16_wcd_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ dev_err(dai->codec->dev,
+ "%s(): substream = %s stream = %d\n", __func__,
+ substream->name, substream->stream);
+}
+
+int msm8x16_wcd_mclk_enable(struct snd_soc_codec *codec,
+ int mclk_enable, bool dapm)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: mclk_enable = %u, dapm = %d\n",
+ __func__, mclk_enable, dapm);
+ if (mclk_enable) {
+ msm8x16_wcd->mclk_enabled = true;
+ msm8x16_wcd_codec_enable_clock_block(codec, 1);
+ } else {
+ if (!msm8x16_wcd->mclk_enabled) {
+ dev_err(codec->dev, "Error, MCLK already diabled\n");
+ return -EINVAL;
+ }
+ msm8x16_wcd->mclk_enabled = false;
+ msm8x16_wcd_codec_enable_clock_block(codec, 0);
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_set_dai_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ dev_err(dai->codec->dev, "%s\n", __func__);
+ return 0;
+}
+
+static int msm8x16_wcd_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ dev_err(dai->codec->dev, "%s\n", __func__);
+ return 0;
+}
+
+static int msm8x16_wcd_set_channel_map(struct snd_soc_dai *dai,
+ unsigned int tx_num, unsigned int *tx_slot,
+ unsigned int rx_num, unsigned int *rx_slot)
+
+{
+ dev_err(dai->codec->dev, "%s\n", __func__);
+ return 0;
+}
+
+static int msm8x16_wcd_get_channel_map(struct snd_soc_dai *dai,
+ unsigned int *tx_num, unsigned int *tx_slot,
+ unsigned int *rx_num, unsigned int *rx_slot)
+
+{
+ dev_err(dai->codec->dev, "%s\n", __func__);
+ return 0;
+}
+
+static int msm8x16_wcd_set_interpolator_rate(struct snd_soc_dai *dai,
+ u8 rx_fs_rate_reg_val, u32 sample_rate)
+{
+ snd_soc_update_bits_wrapper(dai->codec,
+ MSM89XX_CDC_CORE_RX1_B5_CTL, 0xF0, rx_fs_rate_reg_val);
+ snd_soc_update_bits_wrapper(dai->codec,
+ MSM89XX_CDC_CORE_RX2_B5_CTL, 0xF0, rx_fs_rate_reg_val);
+ return 0;
+}
+
+static int msm8x16_wcd_set_decimator_rate(struct snd_soc_dai *dai,
+ u8 tx_fs_rate_reg_val, u32 sample_rate)
+{
+ return 0;
+}
+
+static int msm8x16_wcd_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ u8 tx_fs_rate, rx_fs_rate, rx_clk_fs_rate;
+ int ret;
+
+ dev_err(dai->codec->dev,
+ "%s: dai_name = %s DAI-ID %x rate %d num_ch %d format %d\n",
+ __func__, dai->name, dai->id, params_rate(params),
+ params_channels(params), params_format(params));
+
+ switch (params_rate(params)) {
+ case 8000:
+ tx_fs_rate = 0x00;
+ rx_fs_rate = 0x00;
+ rx_clk_fs_rate = 0x00;
+ break;
+ case 16000:
+ tx_fs_rate = 0x20;
+ rx_fs_rate = 0x20;
+ rx_clk_fs_rate = 0x01;
+ break;
+ case 32000:
+ tx_fs_rate = 0x40;
+ rx_fs_rate = 0x40;
+ rx_clk_fs_rate = 0x02;
+ break;
+ case 48000:
+ tx_fs_rate = 0x60;
+ rx_fs_rate = 0x60;
+ rx_clk_fs_rate = 0x03;
+ break;
+ case 96000:
+ tx_fs_rate = 0x80;
+ rx_fs_rate = 0x80;
+ rx_clk_fs_rate = 0x04;
+ break;
+ case 192000:
+ tx_fs_rate = 0xA0;
+ rx_fs_rate = 0xA0;
+ rx_clk_fs_rate = 0x05;
+ break;
+ default:
+ dev_err(dai->codec->dev,
+ "%s: Invalid sampling rate %d\n", __func__,
+ params_rate(params));
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits_wrapper(dai->codec,
+ MSM89XX_CDC_CORE_CLK_RX_I2S_CTL, 0x0F, rx_clk_fs_rate);
+
+ switch (substream->stream) {
+ case SNDRV_PCM_STREAM_CAPTURE:
+ ret = msm8x16_wcd_set_decimator_rate(dai, tx_fs_rate,
+ params_rate(params));
+ if (ret < 0) {
+ dev_err(dai->codec->dev,
+ "%s: set decimator rate failed %d\n", __func__,
+ ret);
+ return ret;
+ }
+ break;
+ case SNDRV_PCM_STREAM_PLAYBACK:
+ ret = msm8x16_wcd_set_interpolator_rate(dai, rx_fs_rate,
+ params_rate(params));
+ if (ret < 0) {
+ dev_err(dai->codec->dev,
+ "%s: set decimator rate failed %d\n", __func__,
+ ret);
+ return ret;
+ }
+ break;
+ default:
+ dev_err(dai->codec->dev,
+ "%s: Invalid stream type %d\n", __func__,
+ substream->stream);
+ return -EINVAL;
+ }
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ snd_soc_update_bits_wrapper(dai->codec,
+ MSM89XX_CDC_CORE_CLK_RX_I2S_CTL, 0x20, 0x20);
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ snd_soc_update_bits_wrapper(dai->codec,
+ MSM89XX_CDC_CORE_CLK_RX_I2S_CTL, 0x20, 0x00);
+ break;
+ default:
+ dev_err(dai->codec->dev, "%s: wrong format selected\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int msm8x16_wcd_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = NULL;
+ u16 tx_vol_ctl_reg = 0;
+ u8 decimator = 0, i;
+ struct msm8x16_wcd_priv *msm8x16_wcd;
+
+ pr_err("%s: Digital Mute val = %d\n", __func__, mute);
+
+ if (!dai || !dai->codec) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
+ codec = dai->codec;
+ msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ if ((dai->id != AIF1_CAP) && (dai->id != AIF2_VIFEED)) {
+ dev_err(codec->dev, "%s: Not capture use case skip\n",
+ __func__);
+ return 0;
+ }
+
+ mute = (mute) ? 1 : 0;
+ if (!mute) {
+ /*
+ * 15 ms is an emperical value for the mute time
+ * that was arrived by checking the pop level
+ * to be inaudible
+ */
+ usleep_range(15000, 15010);
+ }
+
+ for (i = 0; i < NUM_DECIMATORS; i++) {
+ if (msm8x16_wcd->dec_active[i])
+ decimator = i + 1;
+ if (decimator && decimator <= NUM_DECIMATORS) {
+ pr_err("%s: Mute = %d Decimator = %d", __func__,
+ mute, decimator);
+ tx_vol_ctl_reg = MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG +
+ 32 * (decimator - 1);
+ snd_soc_update_bits_wrapper(codec,
+ tx_vol_ctl_reg, 0x01, mute);
+ }
+ decimator = 0;
+ }
+ return 0;
+}
+
+static struct snd_soc_dai_ops msm8x16_wcd_dai_ops = {
+ .startup = msm8x16_wcd_startup,
+ .shutdown = msm8x16_wcd_shutdown,
+ .hw_params = msm8x16_wcd_hw_params,
+ .set_sysclk = msm8x16_wcd_set_dai_sysclk,
+ .set_fmt = msm8x16_wcd_set_dai_fmt,
+ .set_channel_map = msm8x16_wcd_set_channel_map,
+ .get_channel_map = msm8x16_wcd_get_channel_map,
+ .digital_mute = msm8x16_wcd_digital_mute,
+};
+
+static struct snd_soc_dai_driver msm8x16_wcd_i2s_dai[] = {
+ {
+ .name = "msm8x16_wcd_i2s_rx1",
+ .id = AIF1_PB,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .rates = MSM89XX_RATES,
+ .formats = MSM89XX_FORMATS,
+ .rate_max = 192000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 3,
+ },
+ .ops = &msm8x16_wcd_dai_ops,
+ },
+ {
+ .name = "msm8x16_wcd_i2s_tx1",
+ .id = AIF1_CAP,
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .rates = MSM89XX_RATES,
+ .formats = MSM89XX_FORMATS,
+ .rate_max = 192000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 4,
+ },
+ .ops = &msm8x16_wcd_dai_ops,
+ },
+ {
+ .name = "cajon_vifeedback",
+ .id = AIF2_VIFEED,
+ .capture = {
+ .stream_name = "VIfeed",
+ .rates = MSM89XX_RATES,
+ .formats = MSM89XX_FORMATS,
+ .rate_max = 48000,
+ .rate_min = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ },
+ .ops = &msm8x16_wcd_dai_ops,
+ },
+};
+
+static int msm8x16_wcd_codec_enable_rx_chain(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ dev_err(codec->dev,
+ "%s: PMU:Sleeping 20ms after disabling mute\n",
+ __func__);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ dev_err(codec->dev,
+ "%s: PMD:Sleeping 20ms after disabling mute\n",
+ __func__);
+ snd_soc_update_bits_wrapper(codec, w->reg,
+ 1 << w->shift, 0x00);
+ msleep(20);
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_lo_pa(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ dev_err(codec->dev, "%s: %d %s\n", __func__, event, w->name);
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX3_B6_CTL, 0x01, 0x00);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX3_B6_CTL, 0x01, 0x00);
+ break;
+ }
+
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_spk_ext_pa(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ dev_err(codec->dev, "%s: %s event = %d\n", __func__, w->name, event);
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ dev_err(codec->dev,
+ "%s: enable external speaker PA\n", __func__);
+ if (msm8x16_wcd->codec_spk_ext_pa_cb)
+ msm8x16_wcd->codec_spk_ext_pa_cb(codec, 1);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ dev_err(codec->dev,
+ "%s: enable external speaker PA\n", __func__);
+ if (msm8x16_wcd->codec_spk_ext_pa_cb)
+ msm8x16_wcd->codec_spk_ext_pa_cb(codec, 0);
+ break;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ dev_err(codec->dev,
+ "%s: Sleeping 20ms after select EAR PA\n",
+ __func__);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL, 0x80, 0x80);
+ if (get_codec_version(msm8x16_wcd) < CONGA)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_TIME, 0xFF, 0x2A);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ dev_err(codec->dev,
+ "%s: Sleeping 20ms after enabling EAR PA\n",
+ __func__);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL, 0x40, 0x40);
+ usleep_range(7000, 7100);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B6_CTL, 0x01, 0x00);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_RX1_B6_CTL, 0x01, 0x01);
+ msleep(20);
+ msm8x16_wcd->mute_mask |= EAR_PA_DISABLE;
+ if (msm8x16_wcd->boost_option == BOOST_ALWAYS) {
+ dev_err(codec->dev,
+ "%s: boost_option:%d, tear down ear\n",
+ __func__, msm8x16_wcd->boost_option);
+ msm8x16_wcd_boost_mode_sequence(codec, EAR_PMD);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ dev_err(codec->dev,
+ "%s: Sleeping 7ms after disabling EAR PA\n",
+ __func__);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL, 0x40, 0x00);
+ usleep_range(7000, 7100);
+ if (get_codec_version(msm8x16_wcd) < CONGA)
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_TIME, 0xFF, 0x16);
+ break;
+ }
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget msm8x16_wcd_dapm_widgets[] = {
+ /*RX stuff */
+ SND_SOC_DAPM_OUTPUT("EAR"),
+ SND_SOC_DAPM_OUTPUT("WSA_SPK OUT"),
+
+ SND_SOC_DAPM_PGA_E("EAR PA", SND_SOC_NOPM,
+ 0, 0, NULL, 0, msm8x16_wcd_codec_enable_ear_pa,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX("EAR_S", SND_SOC_NOPM, 0, 0,
+ ear_pa_mux),
+
+ SND_SOC_DAPM_MUX("WSA Spk Switch", SND_SOC_NOPM, 0, 0,
+ wsa_spk_mux),
+
+ SND_SOC_DAPM_AIF_IN("I2S RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_AIF_IN("I2S RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_AIF_IN("I2S RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_SUPPLY("INT_LDO_H", SND_SOC_NOPM, 1, 0, NULL, 0),
+
+ SND_SOC_DAPM_SPK("Ext Spk", msm8x16_wcd_codec_enable_spk_ext_pa),
+
+ SND_SOC_DAPM_OUTPUT("HEADPHONE"),
+ SND_SOC_DAPM_PGA_E("HPHL PA", MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN,
+ 5, 0, NULL, 0,
+ msm8x16_wcd_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("HPHL", SND_SOC_NOPM, 0, 0,
+ hphl_mux),
+
+ SND_SOC_DAPM_MIXER_E("HPHL DAC",
+ MSM89XX_PMIC_ANALOG_RX_HPH_L_PA_DAC_CTL, 3, 0, NULL,
+ 0, msm8x16_wcd_hphl_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_PGA_E("HPHR PA", MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN,
+ 4, 0, NULL, 0,
+ msm8x16_wcd_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("HPHR", SND_SOC_NOPM, 0, 0,
+ hphr_mux),
+
+ SND_SOC_DAPM_MIXER_E("HPHR DAC",
+ MSM89XX_PMIC_ANALOG_RX_HPH_R_PA_DAC_CTL, 3, 0, NULL,
+ 0, msm8x16_wcd_hphr_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SPK", SND_SOC_NOPM, 0, 0,
+ spkr_mux),
+
+ SND_SOC_DAPM_DAC("SPK DAC", NULL,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 7, 0),
+
+ SND_SOC_DAPM_MUX("LINE_OUT",
+ SND_SOC_NOPM, 0, 0, lo_mux),
+
+ SND_SOC_DAPM_DAC_E("LINEOUT DAC", NULL,
+ SND_SOC_NOPM, 0, 0, msm8x16_wcd_lo_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ /* Speaker */
+ SND_SOC_DAPM_OUTPUT("SPK_OUT"),
+
+ /* Lineout */
+ SND_SOC_DAPM_OUTPUT("LINEOUT"),
+
+ SND_SOC_DAPM_PGA_E("SPK PA", MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
+ 6, 0, NULL, 0, msm8x16_wcd_codec_enable_spk_pa,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_PGA_E("LINEOUT PA", MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL,
+ 5, 0, NULL, 0, msm8x16_wcd_codec_enable_lo_pa,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY("VDD_SPKDRV", SND_SOC_NOPM, 0, 0,
+ msm89xx_wcd_codec_enable_vdd_spkr,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("Ext Spk Switch", SND_SOC_NOPM, 0, 0,
+ &ext_spk_mux),
+
+ SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MIXER_E("RX1 MIX2",
+ MSM89XX_CDC_CORE_CLK_RX_B1_CTL, MSM89XX_RX1, 0, NULL,
+ 0, msm8x16_wcd_codec_enable_interpolator,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER_E("RX2 MIX2",
+ MSM89XX_CDC_CORE_CLK_RX_B1_CTL, MSM89XX_RX2, 0, NULL,
+ 0, msm8x16_wcd_codec_enable_interpolator,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER_E("RX3 MIX1",
+ MSM89XX_CDC_CORE_CLK_RX_B1_CTL, MSM89XX_RX3, 0, NULL,
+ 0, msm8x16_wcd_codec_enable_interpolator,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY("RX1 CLK", MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("RX2 CLK", MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 1, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("RX3 CLK", MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 2, 0, msm8x16_wcd_codec_enable_dig_clk, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER_E("RX1 CHAIN", MSM89XX_CDC_CORE_RX1_B6_CTL, 0, 0,
+ NULL, 0,
+ msm8x16_wcd_codec_enable_rx_chain,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER_E("RX2 CHAIN", MSM89XX_CDC_CORE_RX2_B6_CTL, 0, 0,
+ NULL, 0,
+ msm8x16_wcd_codec_enable_rx_chain,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER_E("RX3 CHAIN", MSM89XX_CDC_CORE_RX3_B6_CTL, 0, 0,
+ NULL, 0,
+ msm8x16_wcd_codec_enable_rx_chain,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp3_mux),
+
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp3_mux),
+
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp3_mux),
+
+ SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+ &rx1_mix2_inp1_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+ &rx2_mix2_inp1_mux),
+
+ SND_SOC_DAPM_SUPPLY("MICBIAS_REGULATOR", SND_SOC_NOPM,
+ ON_DEMAND_MICBIAS, 0,
+ msm8x16_wcd_codec_enable_on_demand_supply,
+ SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY("CP", MSM89XX_PMIC_ANALOG_NCP_EN, 0, 0,
+ msm8x16_wcd_codec_enable_charge_pump, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY("EAR CP", MSM89XX_PMIC_ANALOG_NCP_EN, 4, 0,
+ msm8x16_wcd_codec_enable_charge_pump, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY_S("RX_BIAS", 1, SND_SOC_NOPM,
+ 0, 0, msm8x16_wcd_codec_enable_rx_bias,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY_S("SPK_RX_BIAS", 1, SND_SOC_NOPM, 0, 0,
+ msm8x16_wcd_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ /* TX */
+
+ SND_SOC_DAPM_SUPPLY_S("CDC_CONN", -2, MSM89XX_CDC_CORE_CLK_OTHR_CTL,
+ 2, 0, NULL, 0),
+
+
+ SND_SOC_DAPM_INPUT("AMIC1"),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS Internal1",
+ MSM89XX_PMIC_ANALOG_MICB_1_EN, 7, 0,
+ msm8x16_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS Internal2",
+ MSM89XX_PMIC_ANALOG_MICB_2_EN, 7, 0,
+ msm8x16_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS Internal3",
+ MSM89XX_PMIC_ANALOG_MICB_1_EN, 7, 0,
+ msm8x16_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("ADC1", NULL, MSM89XX_PMIC_ANALOG_TX_1_EN, 7, 0,
+ msm8x16_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("ADC2_INP2",
+ NULL, MSM89XX_PMIC_ANALOG_TX_2_EN, 7, 0,
+ msm8x16_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("ADC2_INP3",
+ NULL, MSM89XX_PMIC_ANALOG_TX_3_EN, 7, 0,
+ msm8x16_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MIXER("ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0,
+ &tx_adc2_mux),
+
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS External",
+ MSM89XX_PMIC_ANALOG_MICB_1_EN, 7, 0,
+ msm8x16_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS External2",
+ MSM89XX_PMIC_ANALOG_MICB_2_EN, 7, 0,
+ msm8x16_wcd_codec_enable_micbias, SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+
+ SND_SOC_DAPM_INPUT("AMIC3"),
+
+ SND_SOC_DAPM_MUX_E("DEC1 MUX",
+ MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL, 0, 0,
+ &dec1_mux, msm8x16_wcd_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC2 MUX",
+ MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL, 1, 0,
+ &dec2_mux, msm8x16_wcd_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC3 MUX",
+ MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL, 2, 0,
+ &dec3_mux, msm8x16_wcd_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC4 MUX",
+ MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL, 3, 0,
+ &dec4_mux, msm8x16_wcd_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("RDAC2 MUX", SND_SOC_NOPM, 0, 0, &rdac2_mux),
+
+ SND_SOC_DAPM_INPUT("AMIC2"),
+
+ SND_SOC_DAPM_AIF_OUT("I2S TX1", "AIF1 Capture", 0, SND_SOC_NOPM,
+ 0, 0),
+ SND_SOC_DAPM_AIF_OUT("I2S TX2", "AIF1 Capture", 0, SND_SOC_NOPM,
+ 0, 0),
+ SND_SOC_DAPM_AIF_OUT("I2S TX3", "AIF1 Capture", 0, SND_SOC_NOPM,
+ 0, 0),
+
+ SND_SOC_DAPM_AIF_OUT("AIF2 VI", "VIfeed", 0, SND_SOC_NOPM,
+ 0, 0),
+ /* Digital Mic Inputs */
+ SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+ msm8x16_wcd_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+ msm8x16_wcd_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_INPUT("DMIC3"),
+
+ SND_SOC_DAPM_INPUT("DMIC4"),
+
+ /* Sidetone */
+ SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
+ SND_SOC_DAPM_PGA_E("IIR1", MSM89XX_CDC_CORE_CLK_SD_CTL, 0, 0, NULL, 0,
+ msm8x16_wcd_codec_set_iir_gain, SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_MUX("IIR2 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir2_inp1_mux),
+ SND_SOC_DAPM_PGA_E("IIR2", MSM89XX_CDC_CORE_CLK_SD_CTL, 1, 0, NULL, 0,
+ msm8x16_wcd_codec_set_iir_gain, SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_SUPPLY("RX_I2S_CLK",
+ MSM89XX_CDC_CORE_CLK_RX_I2S_CTL, 4, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("TX_I2S_CLK",
+ MSM89XX_CDC_CORE_CLK_TX_I2S_CTL, 4, 0,
+ NULL, 0),
+};
+
+static const struct msm8x16_wcd_reg_mask_val msm8x16_wcd_reg_defaults[] = {
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x03),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_CURRENT_LIMIT, 0x82),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL, 0xE1),
+};
+
+static const struct msm8x16_wcd_reg_mask_val msm8x16_wcd_reg_defaults_2_0[] = {
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_SEC_ACCESS, 0xA5),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3, 0x0F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_TX_1_2_OPAMP_BIAS, 0x4F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_NCP_FBCTRL, 0x28),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL, 0x69),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG, 0x01),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_BOOST_EN_CTL, 0x5F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SLOPE_COMP_IP_ZERO, 0x88),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SEC_ACCESS, 0xA5),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3, 0x0F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_CURRENT_LIMIT, 0x82),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x03),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL, 0xE1),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_CDC_RST_CTL, 0x80),
+};
+
+static const struct msm8x16_wcd_reg_mask_val msm8909_wcd_reg_defaults[] = {
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_SEC_ACCESS, 0xA5),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3, 0x0F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SEC_ACCESS, 0xA5),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3, 0x0F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_TX_1_2_OPAMP_BIAS, 0x4C),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_NCP_FBCTRL, 0x28),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL, 0x69),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG, 0x01),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_PERPH_SUBTYPE, 0x0A),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x03),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL, 0xE1),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_CDC_RST_CTL, 0x80),
+};
+
+static const struct msm8x16_wcd_reg_mask_val cajon_wcd_reg_defaults[] = {
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_SEC_ACCESS, 0xA5),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3, 0x0F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SEC_ACCESS, 0xA5),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3, 0x0F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_TX_1_2_OPAMP_BIAS, 0x4C),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_CURRENT_LIMIT, 0x82),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_NCP_FBCTRL, 0xA8),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_NCP_VCTRL, 0xA4),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_ANA_BIAS_SET, 0x41),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL, 0x69),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG, 0x01),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL, 0xE1),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x03),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_PA, 0xFA),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_CDC_RST_CTL, 0x80),
+};
+
+static const struct msm8x16_wcd_reg_mask_val cajon2p0_wcd_reg_defaults[] = {
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_SEC_ACCESS, 0xA5),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3, 0x0F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SEC_ACCESS, 0xA5),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3, 0x0F),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_TX_1_2_OPAMP_BIAS, 0x4C),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_CURRENT_LIMIT, 0xA2),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_NCP_FBCTRL, 0xA8),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_NCP_VCTRL, 0xA4),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_ANA_BIAS_SET, 0x41),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL, 0x69),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG, 0x01),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL, 0xE1),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x03),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_RX_EAR_STATUS, 0x10),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_BYPASS_MODE, 0x18),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_PA, 0xFA),
+ MSM89XX_REG_VAL(MSM89XX_PMIC_DIGITAL_CDC_RST_CTL, 0x80),
+};
+
+static void msm8x16_wcd_update_reg_defaults(struct snd_soc_codec *codec)
+{
+ u32 i, version;
+ struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
+
+ version = get_codec_version(msm8x16_wcd);
+ if (version == TOMBAK_1_0) {
+ for (i = 0; i < ARRAY_SIZE(msm8x16_wcd_reg_defaults); i++)
+ snd_soc_write_wrapper(codec,
+ msm8x16_wcd_reg_defaults[i].reg,
+ msm8x16_wcd_reg_defaults[i].val);
+ } else if (version == TOMBAK_2_0) {
+ for (i = 0; i < ARRAY_SIZE(msm8x16_wcd_reg_defaults_2_0); i++)
+ snd_soc_write_wrapper(codec,
+ msm8x16_wcd_reg_defaults_2_0[i].reg,
+ msm8x16_wcd_reg_defaults_2_0[i].val);
+ } else if (version == CONGA) {
+ for (i = 0; i < ARRAY_SIZE(msm8909_wcd_reg_defaults); i++)
+ snd_soc_write_wrapper(codec,
+ msm8909_wcd_reg_defaults[i].reg,
+ msm8909_wcd_reg_defaults[i].val);
+ } else if (version == CAJON) {
+ for (i = 0; i < ARRAY_SIZE(cajon_wcd_reg_defaults); i++)
+ snd_soc_write_wrapper(codec,
+ cajon_wcd_reg_defaults[i].reg,
+ cajon_wcd_reg_defaults[i].val);
+ } else if (version == CAJON_2_0 || version == DIANGU) {
+ for (i = 0; i < ARRAY_SIZE(cajon2p0_wcd_reg_defaults); i++)
+ snd_soc_write_wrapper(codec,
+ cajon2p0_wcd_reg_defaults[i].reg,
+ cajon2p0_wcd_reg_defaults[i].val);
+ }
+}
+
+static const struct msm8x16_wcd_reg_mask_val
+ msm8x16_wcd_codec_reg_init_val[] = {
+
+ /* Initialize current threshold to 350MA
+ * number of wait and run cycles to 4096
+ */
+ {MSM89XX_PMIC_ANALOG_RX_COM_OCP_CTL, 0xFF, 0x12},
+ {MSM89XX_PMIC_ANALOG_RX_COM_OCP_COUNT, 0xFF, 0xFF},
+};
+
+static void msm8x16_wcd_codec_init_reg(struct snd_soc_codec *codec)
+{
+ u32 i;
+
+ for (i = 0; i < ARRAY_SIZE(msm8x16_wcd_codec_reg_init_val); i++)
+ snd_soc_update_bits_wrapper(codec,
+ msm8x16_wcd_codec_reg_init_val[i].reg,
+ msm8x16_wcd_codec_reg_init_val[i].mask,
+ msm8x16_wcd_codec_reg_init_val[i].val);
+}
+
+static int msm8x16_wcd_bringup(struct snd_soc_codec *codec)
+{
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_SEC_ACCESS,
+ 0xA5);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL4, 0x01);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SEC_ACCESS,
+ 0xA5);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL4, 0x01);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_SEC_ACCESS,
+ 0xA5);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL4, 0x00);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SEC_ACCESS,
+ 0xA5);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL4, 0x00);
+ return 0;
+}
+
+static struct regulator *wcd8x16_wcd_codec_find_regulator(
+ const struct msm8x16_wcd *msm8x16,
+ const char *name)
+{
+ int i;
+
+ for (i = 0; i < msm8x16->num_of_supplies; i++) {
+ if (msm8x16->supplies[i].supply &&
+ !strcmp(msm8x16->supplies[i].supply, name))
+ return msm8x16->supplies[i].consumer;
+ }
+
+ dev_err(msm8x16->dev, "Error: regulator not found:%s\n"
+ , name);
+ return NULL;
+}
+
+static int msm8x16_wcd_device_down(struct snd_soc_codec *codec)
+{
+ struct msm8916_asoc_mach_data *pdata = NULL;
+ struct msm8x16_wcd_priv *msm8x16_wcd_priv =
+ snd_soc_codec_get_drvdata(codec);
+ int i;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ dev_err(codec->dev, "%s: device down!\n", __func__);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_TX_1_EN, 0x3);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_TX_2_EN, 0x3);
+ if (msm8x16_wcd_priv->boost_option == BOOST_ON_FOREVER) {
+ if ((snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL)
+ & 0x80) == 0) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_MCLK_CTL, 0x01, 0x01);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_CDC_CORE_CLK_PDM_CTL, 0x03, 0x03);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL, 0x30);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_RST_CTL, 0x80, 0x80);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_TOP_CLK_CTL,
+ 0x0C, 0x0C);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL,
+ 0x84, 0x84);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL,
+ 0x10, 0x10);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL,
+ 0x1F, 0x1F);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC,
+ 0x90, 0x90);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL,
+ 0xFF, 0xFF);
+ usleep_range(20, 21);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL,
+ 0xFF, 0xFF);
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
+ 0xE9, 0xE9);
+ }
+ }
+ msm8x16_wcd_boost_off(codec);
+ msm8x16_wcd_priv->hph_mode = NORMAL_MODE;
+ for (i = 0; i < MSM89XX_RX_MAX; i++)
+ msm8x16_wcd_priv->comp_enabled[i] = COMPANDER_NONE;
+
+ /* 40ms to allow boost to discharge */
+ msleep(40);
+ /* Disable PA to avoid pop during codec bring up */
+ snd_soc_update_bits_wrapper(codec, MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN,
+ 0x30, 0x00);
+ snd_soc_update_bits_wrapper(codec, MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
+ 0x80, 0x00);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_L_PA_DAC_CTL, 0x20);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_HPH_R_PA_DAC_CTL, 0x20);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_RX_EAR_CTL, 0x12);
+ snd_soc_write_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x93);
+
+ msm8x16_wcd_bringup(codec);
+ atomic_set(&pdata->mclk_enabled, false);
+ set_bit(BUS_DOWN, &msm8x16_wcd_priv->status_mask);
+ snd_soc_card_change_online_state(codec->component.card, 0);
+ return 0;
+}
+
+static int msm8x16_wcd_device_up(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd_priv =
+ snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+
+ dev_err(codec->dev, "%s: device up!\n", __func__);
+
+ clear_bit(BUS_DOWN, &msm8x16_wcd_priv->status_mask);
+
+ snd_soc_card_change_online_state(codec->component.card, 1);
+ /* delay is required to make sure sound card state updated */
+ usleep_range(5000, 5100);
+
+ msm8x16_wcd_codec_init_reg(codec);
+ msm8x16_wcd_update_reg_defaults(codec);
+
+ snd_soc_write_wrapper(codec, MSM89XX_PMIC_DIGITAL_INT_EN_SET,
+ MSM89XX_PMIC_DIGITAL_INT_EN_SET__POR);
+ snd_soc_write_wrapper(codec, MSM89XX_PMIC_DIGITAL_INT_EN_CLR,
+ MSM89XX_PMIC_DIGITAL_INT_EN_CLR__POR);
+
+ msm8x16_wcd_set_boost_v(codec);
+
+ msm8x16_wcd_set_micb_v(codec);
+ if (msm8x16_wcd_priv->boost_option == BOOST_ON_FOREVER)
+ msm8x16_wcd_boost_on(codec);
+ else if (msm8x16_wcd_priv->boost_option == BYPASS_ALWAYS)
+ msm8x16_wcd_bypass_on(codec);
+
+ msm8x16_wcd_configure_cap(codec, false, false);
+ wcd_mbhc_stop(&msm8x16_wcd_priv->mbhc);
+ wcd_mbhc_deinit(&msm8x16_wcd_priv->mbhc);
+ ret = wcd_mbhc_init(&msm8x16_wcd_priv->mbhc, codec, &mbhc_cb, &intr_ids,
+ wcd_mbhc_registers, true);
+ if (ret)
+ dev_err(codec->dev, "%s: mbhc initialization failed\n",
+ __func__);
+ else
+ wcd_mbhc_start(&msm8x16_wcd_priv->mbhc,
+ msm8x16_wcd_priv->mbhc.mbhc_cfg);
+
+
+ return 0;
+}
+
+static int adsp_state_callback(struct notifier_block *nb, unsigned long value,
+ void *priv)
+{
+ bool timedout;
+ unsigned long timeout;
+
+ if (value == SUBSYS_BEFORE_SHUTDOWN)
+ msm8x16_wcd_device_down(registered_codec);
+ else if (value == SUBSYS_AFTER_POWERUP) {
+
+ dev_err(registered_codec->dev,
+ "ADSP is about to power up. bring up codec\n");
+
+ if (!q6core_is_adsp_ready()) {
+ dev_err(registered_codec->dev,
+ "ADSP isn't ready\n");
+ timeout = jiffies +
+ msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
+ while (!(timedout = time_after(jiffies, timeout))) {
+ if (!q6core_is_adsp_ready()) {
+ dev_err(registered_codec->dev,
+ "ADSP isn't ready\n");
+ } else {
+ dev_err(registered_codec->dev,
+ "ADSP is ready\n");
+ break;
+ }
+ }
+ } else {
+ dev_err(registered_codec->dev,
+ "%s: DSP is ready\n", __func__);
+ }
+
+ msm8x16_wcd_device_up(registered_codec);
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block adsp_state_notifier_block = {
+ .notifier_call = adsp_state_callback,
+ .priority = -INT_MAX,
+};
+
+int msm8x16_wcd_hs_detect(struct snd_soc_codec *codec,
+ struct wcd_mbhc_config *mbhc_cfg)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd_priv =
+ snd_soc_codec_get_drvdata(codec);
+
+ return wcd_mbhc_start(&msm8x16_wcd_priv->mbhc, mbhc_cfg);
+}
+EXPORT_SYMBOL(msm8x16_wcd_hs_detect);
+
+void msm8x16_wcd_hs_detect_exit(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd_priv =
+ snd_soc_codec_get_drvdata(codec);
+
+ wcd_mbhc_stop(&msm8x16_wcd_priv->mbhc);
+}
+EXPORT_SYMBOL(msm8x16_wcd_hs_detect_exit);
+
+void msm8x16_update_int_spk_boost(bool enable)
+{
+ pr_err("%s: enable = %d\n", __func__, enable);
+ spkr_boost_en = enable;
+}
+EXPORT_SYMBOL(msm8x16_update_int_spk_boost);
+
+static void msm8x16_wcd_set_micb_v(struct snd_soc_codec *codec)
+{
+
+ struct msm8x16_wcd *msm8x16 = codec->control_data;
+ struct msm8x16_wcd_pdata *pdata = msm8x16->dev->platform_data;
+ u8 reg_val;
+
+ reg_val = VOLTAGE_CONVERTER(pdata->micbias.cfilt1_mv, MICBIAS_MIN_VAL,
+ MICBIAS_STEP_SIZE);
+ dev_err(codec->dev, "cfilt1_mv %d reg_val %x\n",
+ (u32)pdata->micbias.cfilt1_mv, reg_val);
+ snd_soc_update_bits_wrapper(codec, MSM89XX_PMIC_ANALOG_MICB_1_VAL,
+ 0xF8, (reg_val << 3));
+}
+
+static void msm8x16_wcd_set_boost_v(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd_priv =
+ snd_soc_codec_get_drvdata(codec);
+
+ snd_soc_update_bits_wrapper(codec, MSM89XX_PMIC_ANALOG_OUTPUT_VOLTAGE,
+ 0x1F, msm8x16_wcd_priv->boost_voltage);
+}
+
+static void msm8x16_wcd_configure_cap(struct snd_soc_codec *codec,
+ bool micbias1, bool micbias2)
+{
+
+ struct msm8916_asoc_mach_data *pdata = NULL;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+
+ pr_err("\n %s: micbias1 %x micbias2 = %d\n", __func__, micbias1,
+ micbias2);
+ if (micbias1 && micbias2) {
+ if ((pdata->micbias1_cap_mode
+ == MICBIAS_EXT_BYP_CAP) ||
+ (pdata->micbias2_cap_mode
+ == MICBIAS_EXT_BYP_CAP))
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_EN,
+ 0x40, (MICBIAS_EXT_BYP_CAP << 6));
+ else
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_EN,
+ 0x40, (MICBIAS_NO_EXT_BYP_CAP << 6));
+ } else if (micbias2) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_EN,
+ 0x40, (pdata->micbias2_cap_mode << 6));
+ } else if (micbias1) {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_EN,
+ 0x40, (pdata->micbias1_cap_mode << 6));
+ } else {
+ snd_soc_update_bits_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_MICB_1_EN,
+ 0x40, 0x00);
+ }
+}
+
+static int msm89xx_digcodec_probe(struct snd_soc_codec *codec)
+{
+ registered_digcodec = codec;
+
+ return 0;
+}
+
+
+static int msm89xx_digcodec_remove(struct snd_soc_codec *codec)
+{
+ return 0;
+}
+
+static int msm8x16_wcd_codec_probe(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd_priv;
+ int i, ret;
+
+ dev_err(codec->dev, "%s()\n", __func__);
+
+ msm8x16_wcd_priv = kzalloc(sizeof(struct msm8x16_wcd_priv), GFP_KERNEL);
+ if (!msm8x16_wcd_priv)
+ return -ENOMEM;
+
+ for (i = 0; i < NUM_DECIMATORS; i++) {
+ tx_hpf_work[i].msm8x16_wcd = msm8x16_wcd_priv;
+ tx_hpf_work[i].decimator = i + 1;
+ INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
+ tx_hpf_corner_freq_callback);
+ }
+
+ codec->control_data = dev_get_drvdata(codec->dev);
+ snd_soc_codec_set_drvdata(codec, msm8x16_wcd_priv);
+ msm8x16_wcd_priv->codec = codec;
+
+ msm8x16_wcd_priv->spkdrv_reg =
+ wcd8x16_wcd_codec_find_regulator(codec->control_data,
+ MSM89XX_VDD_SPKDRV_NAME);
+ msm8x16_wcd_priv->pmic_rev = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_REVISION1);
+ msm8x16_wcd_priv->codec_version = snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_DIGITAL_PERPH_SUBTYPE);
+ if (msm8x16_wcd_priv->codec_version == CONGA) {
+ dev_err(codec->dev, "%s :Conga REV: %d\n", __func__,
+ msm8x16_wcd_priv->codec_version);
+ msm8x16_wcd_priv->ext_spk_boost_set = true;
+ } else {
+ dev_err(codec->dev, "%s :PMIC REV: %d\n", __func__,
+ msm8x16_wcd_priv->pmic_rev);
+ if (msm8x16_wcd_priv->pmic_rev == TOMBAK_1_0 &&
+ msm8x16_wcd_priv->codec_version == CAJON_2_0) {
+ msm8x16_wcd_priv->codec_version = DIANGU;
+ dev_err(codec->dev, "%s : Diangu detected\n",
+ __func__);
+ } else if (msm8x16_wcd_priv->pmic_rev == TOMBAK_1_0 &&
+ (snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_NCP_FBCTRL)
+ & 0x80)) {
+ msm8x16_wcd_priv->codec_version = CAJON;
+ dev_err(codec->dev, "%s : Cajon detected\n", __func__);
+ } else if (msm8x16_wcd_priv->pmic_rev == TOMBAK_2_0 &&
+ (snd_soc_read_wrapper(codec,
+ MSM89XX_PMIC_ANALOG_NCP_FBCTRL)
+ & 0x80)) {
+ msm8x16_wcd_priv->codec_version = CAJON_2_0;
+ dev_err(codec->dev, "%s : Cajon 2.0 detected\n",
+ __func__);
+ }
+ }
+ /*
+ * set to default boost option BOOST_SWITCH, user mixer path can change
+ * it to BOOST_ALWAYS or BOOST_BYPASS based on solution chosen.
+ */
+ msm8x16_wcd_priv->boost_option = BOOST_SWITCH;
+ msm8x16_wcd_priv->hph_mode = NORMAL_MODE;
+
+ for (i = 0; i < MSM89XX_RX_MAX; i++)
+ msm8x16_wcd_priv->comp_enabled[i] = COMPANDER_NONE;
+
+ msm8x16_wcd_dt_parse_boost_info(codec);
+ msm8x16_wcd_set_boost_v(codec);
+
+ snd_soc_add_codec_controls(codec, impedance_detect_controls,
+ ARRAY_SIZE(impedance_detect_controls));
+ snd_soc_add_codec_controls(codec, hph_type_detect_controls,
+ ARRAY_SIZE(hph_type_detect_controls));
+
+ msm8x16_wcd_bringup(codec);
+ msm8x16_wcd_codec_init_reg(codec);
+ msm8x16_wcd_update_reg_defaults(codec);
+
+ wcd9xxx_spmi_set_codec(codec);
+
+ msm8x16_wcd_priv->on_demand_list[ON_DEMAND_MICBIAS].supply =
+ wcd8x16_wcd_codec_find_regulator(
+ codec->control_data,
+ on_demand_supply_name[ON_DEMAND_MICBIAS]);
+ atomic_set(&msm8x16_wcd_priv->on_demand_list[ON_DEMAND_MICBIAS].ref, 0);
+
+ BLOCKING_INIT_NOTIFIER_HEAD(&msm8x16_wcd_priv->notifier);
+
+ msm8x16_wcd_priv->fw_data = kzalloc(sizeof(*(msm8x16_wcd_priv->fw_data))
+ , GFP_KERNEL);
+ if (!msm8x16_wcd_priv->fw_data) {
+ kfree(msm8x16_wcd_priv);
+ return -ENOMEM;
+ }
+
+ set_bit(WCD9XXX_MBHC_CAL, msm8x16_wcd_priv->fw_data->cal_bit);
+ ret = wcd_cal_create_hwdep(msm8x16_wcd_priv->fw_data,
+ WCD9XXX_CODEC_HWDEP_NODE, codec);
+ if (ret < 0) {
+ dev_err(codec->dev, "%s hwdep failed %d\n", __func__, ret);
+ kfree(msm8x16_wcd_priv->fw_data);
+ kfree(msm8x16_wcd_priv);
+ return ret;
+ }
+
+ wcd_mbhc_init(&msm8x16_wcd_priv->mbhc, codec, &mbhc_cb, &intr_ids,
+ wcd_mbhc_registers, true);
+
+ msm8x16_wcd_priv->mclk_enabled = false;
+ msm8x16_wcd_priv->clock_active = false;
+ msm8x16_wcd_priv->config_mode_active = false;
+
+ /*Update speaker boost configuration*/
+ msm8x16_wcd_priv->spk_boost_set = spkr_boost_en;
+ pr_err("%s: speaker boost configured = %d\n",
+ __func__, msm8x16_wcd_priv->spk_boost_set);
+
+ /* Set initial MICBIAS voltage level */
+ msm8x16_wcd_set_micb_v(codec);
+
+ /* Set initial cap mode */
+ msm8x16_wcd_configure_cap(codec, false, false);
+ registered_codec = codec;
+ adsp_state_notifier =
+ subsys_notif_register_notifier("adsp",
+ &adsp_state_notifier_block);
+ if (!adsp_state_notifier) {
+ dev_err(codec->dev, "Failed to register adsp state notifier\n");
+ kfree(msm8x16_wcd_priv->fw_data);
+ kfree(msm8x16_wcd_priv);
+ registered_codec = NULL;
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int msm8x16_wcd_codec_remove(struct snd_soc_codec *codec)
+{
+ struct msm8x16_wcd_priv *msm8x16_wcd_priv =
+ snd_soc_codec_get_drvdata(codec);
+ struct msm8x16_wcd *msm8x16_wcd;
+
+ msm8x16_wcd = codec->control_data;
+ msm8x16_wcd_priv->spkdrv_reg = NULL;
+ msm8x16_wcd_priv->on_demand_list[ON_DEMAND_MICBIAS].supply = NULL;
+ atomic_set(&msm8x16_wcd_priv->on_demand_list[ON_DEMAND_MICBIAS].ref, 0);
+ kfree(msm8x16_wcd_priv->fw_data);
+ kfree(msm8x16_wcd_priv);
+
+ return 0;
+}
+
+static int msm8x16_wcd_enable_static_supplies_to_optimum(
+ struct msm8x16_wcd *msm8x16,
+ struct msm8x16_wcd_pdata *pdata)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < msm8x16->num_of_supplies; i++) {
+ if (pdata->regulator[i].ondemand)
+ continue;
+ if (regulator_count_voltages(msm8x16->supplies[i].consumer) <=
+ 0)
+ continue;
+
+ ret = regulator_set_voltage(msm8x16->supplies[i].consumer,
+ pdata->regulator[i].min_uv,
+ pdata->regulator[i].max_uv);
+ if (ret) {
+ dev_err(msm8x16->dev,
+ "Setting volt failed for regulator %s err %d\n",
+ msm8x16->supplies[i].supply, ret);
+ }
+
+ ret = regulator_set_load(msm8x16->supplies[i].consumer,
+ pdata->regulator[i].optimum_ua);
+ dev_err(msm8x16->dev, "Regulator %s set optimum mode\n",
+ msm8x16->supplies[i].supply);
+ }
+
+ return ret;
+}
+
+static int msm8x16_wcd_disable_static_supplies_to_optimum(
+ struct msm8x16_wcd *msm8x16,
+ struct msm8x16_wcd_pdata *pdata)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < msm8x16->num_of_supplies; i++) {
+ if (pdata->regulator[i].ondemand)
+ continue;
+ if (regulator_count_voltages(msm8x16->supplies[i].consumer) <=
+ 0)
+ continue;
+ regulator_set_voltage(msm8x16->supplies[i].consumer, 0,
+ pdata->regulator[i].max_uv);
+ regulator_set_load(msm8x16->supplies[i].consumer, 0);
+ dev_err(msm8x16->dev, "Regulator %s set optimum mode\n",
+ msm8x16->supplies[i].supply);
+ }
+
+ return ret;
+}
+
+int msm8x16_wcd_suspend(struct snd_soc_codec *codec)
+{
+ struct msm8916_asoc_mach_data *pdata = NULL;
+ struct msm8x16_wcd *msm8x16 = codec->control_data;
+ struct msm8x16_wcd_pdata *msm8x16_pdata = msm8x16->dev->platform_data;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ pr_err("%s: mclk cnt = %d, mclk_enabled = %d\n",
+ __func__, atomic_read(&pdata->mclk_rsc_ref),
+ atomic_read(&pdata->mclk_enabled));
+ if (atomic_read(&pdata->mclk_enabled) == true) {
+ cancel_delayed_work_sync(
+ &pdata->disable_mclk_work);
+ mutex_lock(&pdata->cdc_mclk_mutex);
+ if (atomic_read(&pdata->mclk_enabled) == true) {
+ if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
+ pdata->digital_cdc_clk.clk_val = 0;
+ afe_set_digital_codec_core_clock(
+ AFE_PORT_ID_PRIMARY_MI2S_RX,
+ &pdata->digital_cdc_clk);
+ } else {
+ pdata->digital_cdc_core_clk.enable = 0;
+ afe_set_lpass_clock_v2(
+ AFE_PORT_ID_PRIMARY_MI2S_RX,
+ &pdata->digital_cdc_core_clk);
+ }
+ atomic_set(&pdata->mclk_enabled, false);
+ }
+ mutex_unlock(&pdata->cdc_mclk_mutex);
+ }
+ msm8x16_wcd_disable_static_supplies_to_optimum(msm8x16, msm8x16_pdata);
+ return 0;
+}
+
+int msm8x16_wcd_resume(struct snd_soc_codec *codec)
+{
+ struct msm8916_asoc_mach_data *pdata = NULL;
+ struct msm8x16_wcd *msm8x16 = codec->control_data;
+ struct msm8x16_wcd_pdata *msm8x16_pdata = msm8x16->dev->platform_data;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ msm8x16_wcd_enable_static_supplies_to_optimum(msm8x16, msm8x16_pdata);
+ return 0;
+}
+
+static struct regmap *msm89xx_pmic_cdc_regmap;
+static struct regmap *msm89xx_pmic_cdc_get_regmap(struct device *dev)
+{
+ return msm89xx_pmic_cdc_regmap;
+}
+
+static const struct snd_soc_codec_driver soc_codec_dev_msm8x16_wcd = {
+ .probe = msm8x16_wcd_codec_probe,
+ .remove = msm8x16_wcd_codec_remove,
+
+ .suspend = msm8x16_wcd_suspend,
+ .resume = msm8x16_wcd_resume,
+
+ .controls = msm8x16_wcd_snd_controls,
+ .num_controls = ARRAY_SIZE(msm8x16_wcd_snd_controls),
+ .dapm_widgets = msm8x16_wcd_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(msm8x16_wcd_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
+ .get_regmap = msm89xx_pmic_cdc_get_regmap,
+};
+
+static int msm8x16_wcd_init_supplies(struct msm8x16_wcd *msm8x16,
+ struct msm8x16_wcd_pdata *pdata)
+{
+ int ret;
+ int i;
+
+ msm8x16->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
+ ARRAY_SIZE(pdata->regulator),
+ GFP_KERNEL);
+ if (!msm8x16->supplies) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ msm8x16->num_of_supplies = 0;
+
+ if (ARRAY_SIZE(pdata->regulator) > MAX_REGULATOR) {
+ dev_err(msm8x16->dev, "%s: Array Size out of bound\n",
+ __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+ if (pdata->regulator[i].name) {
+ msm8x16->supplies[i].supply = pdata->regulator[i].name;
+ msm8x16->num_of_supplies++;
+ }
+ }
+
+ ret = regulator_bulk_get(msm8x16->dev, msm8x16->num_of_supplies,
+ msm8x16->supplies);
+ if (ret != 0) {
+ dev_err(msm8x16->dev, "Failed to get supplies: err = %d\n",
+ ret);
+ goto err_supplies;
+ }
+
+ for (i = 0; i < msm8x16->num_of_supplies; i++) {
+ if (regulator_count_voltages(msm8x16->supplies[i].consumer) <=
+ 0)
+ continue;
+
+ ret = regulator_set_voltage(msm8x16->supplies[i].consumer,
+ pdata->regulator[i].min_uv,
+ pdata->regulator[i].max_uv);
+ if (ret) {
+ dev_err(msm8x16->dev, "Setting regulator voltage failed for regulator %s err = %d\n",
+ msm8x16->supplies[i].supply, ret);
+ goto err_get;
+ }
+
+ ret = regulator_set_load(msm8x16->supplies[i].consumer,
+ pdata->regulator[i].optimum_ua);
+ if (ret < 0) {
+ dev_err(msm8x16->dev, "Setting regulator optimum mode failed for regulator %s err = %d\n",
+ msm8x16->supplies[i].supply, ret);
+ goto err_get;
+ } else {
+ ret = 0;
+ }
+ }
+
+ return ret;
+
+err_get:
+ regulator_bulk_free(msm8x16->num_of_supplies, msm8x16->supplies);
+err_supplies:
+ kfree(msm8x16->supplies);
+err:
+ return ret;
+}
+
+static int msm8x16_wcd_enable_static_supplies(struct msm8x16_wcd *msm8x16,
+ struct msm8x16_wcd_pdata *pdata)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < msm8x16->num_of_supplies; i++) {
+ if (pdata->regulator[i].ondemand)
+ continue;
+ ret = regulator_enable(msm8x16->supplies[i].consumer);
+ if (ret) {
+ dev_err(msm8x16->dev, "Failed to enable %s\n",
+ msm8x16->supplies[i].supply);
+ break;
+ }
+ dev_err(msm8x16->dev, "Enabled regulator %s\n",
+ msm8x16->supplies[i].supply);
+ }
+
+ while (ret && --i)
+ if (!pdata->regulator[i].ondemand)
+ regulator_disable(msm8x16->supplies[i].consumer);
+
+ return ret;
+}
+
+
+
+static void msm8x16_wcd_disable_supplies(struct msm8x16_wcd *msm8x16,
+ struct msm8x16_wcd_pdata *pdata)
+{
+ int i;
+
+ regulator_bulk_disable(msm8x16->num_of_supplies,
+ msm8x16->supplies);
+ for (i = 0; i < msm8x16->num_of_supplies; i++) {
+ if (regulator_count_voltages(msm8x16->supplies[i].consumer) <=
+ 0)
+ continue;
+ regulator_set_voltage(msm8x16->supplies[i].consumer, 0,
+ pdata->regulator[i].max_uv);
+ regulator_set_load(msm8x16->supplies[i].consumer, 0);
+ }
+ regulator_bulk_free(msm8x16->num_of_supplies, msm8x16->supplies);
+ kfree(msm8x16->supplies);
+}
+
+static struct snd_soc_dai_driver msm_codec_dais[] = {
+ {
+ .name = "msm-codec-rx",
+ .playback = { /* Support maximum range */
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ },
+ {
+ .name = "msm-codec-tx",
+ .capture = { /* Support maximum range */
+ .stream_name = "Record",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ },
+};
+
+static struct regmap *msm89xx_codec_regmap;
+static struct regmap *msm89xx_codec_get_regmap(struct device *dev)
+{
+ return msm89xx_codec_regmap;
+}
+
+static struct snd_soc_codec_driver soc_msm89xx_codec = {
+ .probe = msm89xx_digcodec_probe,
+ .remove = msm89xx_digcodec_remove,
+ .get_regmap = msm89xx_codec_get_regmap,
+};
+
+static const struct of_device_id msm89xx_codec_of_match[] = {
+ { .compatible = "qcom,msm-codec-core",
+ .data = "msm_codec"},
+ { .compatible = "qcom,pmic-codec-digital",
+ .data = "pmic-digital-codec"},
+ { .compatible = "qcom,pmic-codec-analog",
+ .data = "pmic-analog-codec"},
+ {},
+};
+MODULE_DEVICE_TABLE(of, msm89xx_codec_of_match);
+
+static struct msm8x16_wcd *temp_89xx;
+static int msm89xx_codec_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm8x16_wcd *msm8x16 = NULL;
+ struct msm8x16_wcd_pdata *pdata;
+ int adsp_state;
+ static int dev_registered_cnt;
+ const struct of_device_id *match;
+ const char *addr_prop_name = "qcom,dig-cdc-base-addr";
+ u32 dig_cdc_addr;
+ char __iomem *dig_base;
+
+ adsp_state = apr_get_subsys_state();
+ if (adsp_state != APR_SUBSYS_LOADED) {
+ dev_err(&pdev->dev, "Adsp is not loaded yet %d\n",
+ adsp_state);
+ return -EPROBE_DEFER;
+ }
+
+ match = of_match_node(msm89xx_codec_of_match,
+ pdev->dev.of_node);
+
+ dev_dbg(&pdev->dev, "%s(%d):%s\n",
+ __func__, __LINE__, (char *)match->data);
+
+ if (!strcmp(match->data, "pmic-digital-codec")) {
+ device_init_wakeup(&pdev->dev, true);
+
+ if (pdev->dev.of_node) {
+ dev_err(&pdev->dev, "%s:Platform data from device tree\n",
+ __func__);
+ pdata = msm8x16_wcd_populate_dt_pdata(&pdev->dev);
+ pdev->dev.platform_data = pdata;
+ } else {
+ dev_err(&pdev->dev, "%s:Platform data from board file\n",
+ __func__);
+ pdata = pdev->dev.platform_data;
+ }
+ if (pdata == NULL) {
+ dev_err(&pdev->dev, "%s:Platform data failed to populate\n",
+ __func__);
+ goto rtn;
+ }
+ msm8x16 = kzalloc(sizeof(struct msm8x16_wcd), GFP_KERNEL);
+ if (msm8x16 == NULL) {
+ ret = -ENOMEM;
+ goto rtn;
+ }
+
+ msm8x16->dev = &pdev->dev;
+ ret = msm8x16_wcd_init_supplies(msm8x16, pdata);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Fail to enable Codec supplies\n",
+ __func__);
+ goto err_codec;
+ }
+
+ ret = msm8x16_wcd_enable_static_supplies(msm8x16, pdata);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s: Fail to enable Codec pre-reset supplies\n",
+ __func__);
+ goto err_codec;
+ }
+ usleep_range(5, 6);
+
+ mutex_init(&msm8x16->io_lock);
+ dev_set_drvdata(&pdev->dev, msm8x16);
+ temp_89xx = msm8x16;
+ dev_registered_cnt++;
+ } else if (!strcmp(match->data, "pmic-analog-codec")) {
+ if (wcd9xxx_spmi_irq_init()) {
+ dev_err(&pdev->dev,
+ "%s: irq initialization failed\n", __func__);
+ } else {
+ dev_err(&pdev->dev,
+ "%s: irq initialization passed\n", __func__);
+ }
+ dev_registered_cnt++;
+ } else if (!strcmp(match->data, "msm-codec")) {
+ ret = of_property_read_u32(pdev->dev.of_node, addr_prop_name,
+ &dig_cdc_addr);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
+ __func__, addr_prop_name);
+ dig_cdc_addr = MSM89XX_DIGITAL_CODEC_BASE_ADDR;
+ }
+ dig_base = ioremap(dig_cdc_addr,
+ MSM89XX_DIGITAL_CODEC_REG_SIZE);
+ if (dig_base == NULL) {
+ dev_err(&pdev->dev, "%s ioremap failed\n", __func__);
+ return -ENOMEM;
+ }
+ msm89xx_codec_regmap =
+ devm_regmap_init_mmio_clk(&pdev->dev, NULL,
+ dig_base, &msm89xx_cdc_core_regmap_config);
+ snd_soc_register_codec(&pdev->dev, &soc_msm89xx_codec,
+ msm_codec_dais, ARRAY_SIZE(msm_codec_dais));
+ dev_registered_cnt++;
+ }
+
+ if ((dev_registered_cnt == MAX_MSM89XX_DEVICE) && (!ret)) {
+ msm89xx_pmic_cdc_regmap =
+ devm_regmap_init_spmi_ext(
+ (struct spmi_device *) &pdev->dev.parent,
+ &msm89xx_pmic_cdc_regmap_config);
+ ret = snd_soc_register_codec(temp_89xx->dev,
+ &soc_codec_dev_msm8x16_wcd,
+ msm8x16_wcd_i2s_dai,
+ ARRAY_SIZE(msm8x16_wcd_i2s_dai));
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s:snd_soc_register_codec failed with error %d\n",
+ __func__, ret);
+ goto err_supplies;
+ }
+ }
+ return ret;
+err_supplies:
+ msm8x16_wcd_disable_supplies(msm8x16, pdata);
+err_codec:
+ kfree(msm8x16);
+rtn:
+ return ret;
+}
+
+static int msm89xx_codec_remove(struct platform_device *pdev)
+{
+ struct msm8x16_wcd *msm8x16 = dev_get_drvdata(&pdev->dev);
+
+ mutex_destroy(&msm8x16->io_lock);
+ kfree(msm8x16);
+
+ return 0;
+}
+
+static struct platform_driver msm_codec_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ .of_match_table = of_match_ptr(msm89xx_codec_of_match)
+ },
+ .probe = msm89xx_codec_probe,
+ .remove = msm89xx_codec_remove,
+};
+module_platform_driver(msm_codec_driver);
+
+MODULE_DESCRIPTION("MSM89xx Audio codec driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/msm8x16/msm8x16-wcd.h b/sound/soc/codecs/msm8x16/msm8x16-wcd.h
new file mode 100644
index 000000000000..d2e782b07cb2
--- /dev/null
+++ b/sound/soc/codecs/msm8x16/msm8x16-wcd.h
@@ -0,0 +1,341 @@
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+#ifndef MSM8X16_WCD_H
+#define MSM8X16_WCD_H
+
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/q6afe-v2.h>
+#include "../wcd-mbhc-v2.h"
+#include "../wcdcal-hwdep.h"
+#include "msm8x16_wcd_registers.h"
+
+#define MICBIAS_EXT_BYP_CAP 0x00
+#define MICBIAS_NO_EXT_BYP_CAP 0x01
+
+#define MSM89XX_NUM_IRQ_REGS 2
+#define MAX_REGULATOR 7
+#define MSM89XX_REG_VAL(reg, val) {reg, 0, val}
+#define MSM8X16_TOMBAK_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL 0xFE03B004
+#define MSM8X16_TOMBAK_LPASS_DIGCODEC_CMD_RCGR 0x0181C09C
+#define MSM8X16_TOMBAK_LPASS_DIGCODEC_CFG_RCGR 0x0181C0A0
+#define MSM8X16_TOMBAK_LPASS_DIGCODEC_M 0x0181C0A4
+#define MSM8X16_TOMBAK_LPASS_DIGCODEC_N 0x0181C0A8
+#define MSM8X16_TOMBAK_LPASS_DIGCODEC_D 0x0181C0AC
+#define MSM8X16_TOMBAK_LPASS_DIGCODEC_CBCR 0x0181C0B0
+#define MSM8X16_TOMBAK_LPASS_DIGCODEC_AHB_CBCR 0x0181C0B4
+
+#define MSM8X16_CODEC_NAME "msm8x16_wcd_codec"
+
+#define MSM89XX_IS_CDC_CORE_REG(reg) \
+ (((reg >= 0x00) && (reg <= 0x3FF)) ? 1 : 0)
+#define MSM89XX_IS_PMIC_CDC_REG(reg) \
+ (((reg >= 0xF000) && (reg <= 0xF1FF)) ? 1 : 0)
+/*
+ * MCLK activity indicators during suspend and resume call
+ */
+#define MCLK_SUS_DIS 1
+#define MCLK_SUS_RSC 2
+#define MCLK_SUS_NO_ACT 3
+
+#define NUM_DECIMATORS 4
+#define MSM89XX_VDD_SPKDRV_NAME "cdc-vdd-spkdrv"
+
+#define DEFAULT_MULTIPLIER 800
+#define DEFAULT_GAIN 9
+#define DEFAULT_OFFSET 100
+
+extern const u8 msm89xx_pmic_cdc_reg_readable[MSM89XX_PMIC_CDC_CACHE_SIZE];
+extern const u8 msm89xx_cdc_core_reg_readable[MSM89XX_CDC_CORE_CACHE_SIZE];
+extern struct regmap_config msm89xx_cdc_core_regmap_config;
+extern struct regmap_config msm89xx_pmic_cdc_regmap_config;
+
+enum codec_versions {
+ TOMBAK_1_0,
+ TOMBAK_2_0,
+ CONGA,
+ CAJON,
+ CAJON_2_0,
+ DIANGU,
+ UNSUPPORTED,
+};
+
+/* Support different hph modes */
+enum {
+ NORMAL_MODE = 0,
+ HD2_MODE,
+};
+
+/* Codec supports 1 compander */
+enum {
+ COMPANDER_NONE = 0,
+ COMPANDER_1, /* HPHL/R */
+ COMPANDER_MAX,
+};
+
+enum wcd_curr_ref {
+ I_h4_UA = 0,
+ I_pt5_UA,
+ I_14_UA,
+ I_l4_UA,
+ I_1_UA,
+};
+
+enum wcd_mbhc_imp_det_pin {
+ WCD_MBHC_DET_NONE = 0,
+ WCD_MBHC_DET_HPHL,
+ WCD_MBHC_DET_HPHR,
+ WCD_MBHC_DET_BOTH,
+};
+
+
+/* Each micbias can be assigned to one of three cfilters
+ * Vbatt_min >= .15V + ldoh_v
+ * ldoh_v >= .15v + cfiltx_mv
+ * If ldoh_v = 1.95 160 mv < cfiltx_mv < 1800 mv
+ * If ldoh_v = 2.35 200 mv < cfiltx_mv < 2200 mv
+ * If ldoh_v = 2.75 240 mv < cfiltx_mv < 2600 mv
+ * If ldoh_v = 2.85 250 mv < cfiltx_mv < 2700 mv
+ */
+
+struct wcd9xxx_micbias_setting {
+ u8 ldoh_v;
+ u32 cfilt1_mv; /* in mv */
+ u32 cfilt2_mv; /* in mv */
+ u32 cfilt3_mv; /* in mv */
+ /* Different WCD9xxx series codecs may not
+ * have 4 mic biases. If a codec has fewer
+ * mic biases, some of these properties will
+ * not be used.
+ */
+ u8 bias1_cfilt_sel;
+ u8 bias2_cfilt_sel;
+ u8 bias3_cfilt_sel;
+ u8 bias4_cfilt_sel;
+ u8 bias1_cap_mode;
+ u8 bias2_cap_mode;
+ u8 bias3_cap_mode;
+ u8 bias4_cap_mode;
+ bool bias2_is_headset_only;
+};
+
+enum msm8x16_wcd_pid_current {
+ MSM89XX_PID_MIC_2P5_UA,
+ MSM89XX_PID_MIC_5_UA,
+ MSM89XX_PID_MIC_10_UA,
+ MSM89XX_PID_MIC_20_UA,
+};
+
+struct msm8x16_wcd_reg_mask_val {
+ u16 reg;
+ u8 mask;
+ u8 val;
+};
+
+enum msm8x16_wcd_mbhc_analog_pwr_cfg {
+ MSM89XX_ANALOG_PWR_COLLAPSED = 0,
+ MSM89XX_ANALOG_PWR_ON,
+ MSM89XX_NUM_ANALOG_PWR_CONFIGS,
+};
+
+/* Number of input and output I2S port */
+enum {
+ MSM89XX_RX1 = 0,
+ MSM89XX_RX2,
+ MSM89XX_RX3,
+ MSM89XX_RX_MAX,
+};
+
+enum {
+ MSM89XX_TX1 = 0,
+ MSM89XX_TX2,
+ MSM89XX_TX3,
+ MSM89XX_TX4,
+ MSM89XX_TX_MAX,
+};
+
+enum {
+ /* INTR_REG 0 - Digital Periph */
+ MSM89XX_IRQ_SPKR_CNP = 0,
+ MSM89XX_IRQ_SPKR_CLIP,
+ MSM89XX_IRQ_SPKR_OCP,
+ MSM89XX_IRQ_MBHC_INSREM_DET1,
+ MSM89XX_IRQ_MBHC_RELEASE,
+ MSM89XX_IRQ_MBHC_PRESS,
+ MSM89XX_IRQ_MBHC_INSREM_DET,
+ MSM89XX_IRQ_MBHC_HS_DET,
+ /* INTR_REG 1 - Analog Periph */
+ MSM89XX_IRQ_EAR_OCP,
+ MSM89XX_IRQ_HPHR_OCP,
+ MSM89XX_IRQ_HPHL_OCP,
+ MSM89XX_IRQ_EAR_CNP,
+ MSM89XX_IRQ_HPHR_CNP,
+ MSM89XX_IRQ_HPHL_CNP,
+ MSM89XX_NUM_IRQS,
+};
+
+enum {
+ ON_DEMAND_MICBIAS = 0,
+ ON_DEMAND_SPKDRV,
+ ON_DEMAND_SUPPLIES_MAX,
+};
+
+/*
+ * The delay list is per codec HW specification.
+ * Please add delay in the list in the future instead
+ * of magic number
+ */
+enum {
+ CODEC_DELAY_1_MS = 1000,
+ CODEC_DELAY_1_1_MS = 1100,
+};
+
+struct msm8x16_wcd_regulator {
+ const char *name;
+ int min_uv;
+ int max_uv;
+ int optimum_ua;
+ bool ondemand;
+ struct regulator *regulator;
+};
+
+struct on_demand_supply {
+ struct regulator *supply;
+ atomic_t ref;
+};
+
+struct wcd_imped_i_ref {
+ enum wcd_curr_ref curr_ref;
+ int min_val;
+ int multiplier;
+ int gain_adj;
+ int offset;
+};
+
+struct msm8916_asoc_mach_data {
+ int codec_type;
+ int ext_pa;
+ int us_euro_gpio;
+ int spk_ext_pa_gpio;
+ int mclk_freq;
+ int lb_mode;
+ int afe_clk_ver;
+ u8 micbias1_cap_mode;
+ u8 micbias2_cap_mode;
+ atomic_t mclk_rsc_ref;
+ atomic_t mclk_enabled;
+ atomic_t wsa_mclk_rsc_ref;
+ struct mutex cdc_mclk_mutex;
+ struct mutex wsa_mclk_mutex;
+ struct delayed_work disable_mclk_work;
+ struct afe_digital_clk_cfg digital_cdc_clk;
+ struct afe_clk_set digital_cdc_core_clk;
+ void __iomem *vaddr_gpio_mux_spkr_ctl;
+ void __iomem *vaddr_gpio_mux_mic_ctl;
+ void __iomem *vaddr_gpio_mux_quin_ctl;
+ void __iomem *vaddr_gpio_mux_pcm_ctl;
+ struct on_demand_supply wsa_switch_supply;
+};
+
+struct msm8x16_wcd_pdata {
+ int irq;
+ int irq_base;
+ int num_irqs;
+ int reset_gpio;
+ void *msm8x16_wcd_ahb_base_vaddr;
+ struct wcd9xxx_micbias_setting micbias;
+ struct msm8x16_wcd_regulator regulator[MAX_REGULATOR];
+ u32 mclk_rate;
+ u32 is_lpass;
+};
+
+enum msm8x16_wcd_micbias_num {
+ MSM89XX_MICBIAS1 = 0,
+};
+
+struct msm8x16_wcd {
+ struct device *dev;
+ struct mutex io_lock;
+ u8 version;
+
+ int reset_gpio;
+ int (*read_dev)(struct snd_soc_codec *codec,
+ unsigned short reg);
+ int (*write_dev)(struct snd_soc_codec *codec,
+ unsigned short reg, u8 val);
+
+ u32 num_of_supplies;
+ struct regulator_bulk_data *supplies;
+
+ u8 idbyte[4];
+
+ int num_irqs;
+ u32 mclk_rate;
+};
+
+struct msm8x16_wcd_priv {
+ struct snd_soc_codec *codec;
+ u16 pmic_rev;
+ u16 codec_version;
+ u32 boost_voltage;
+ u32 adc_count;
+ u32 rx_bias_count;
+ s32 dmic_1_2_clk_cnt;
+ u32 mute_mask;
+ bool mclk_enabled;
+ bool clock_active;
+ bool config_mode_active;
+ u16 boost_option;
+ /* mode to select hd2 */
+ u32 hph_mode;
+ /* compander used for each rx chain */
+ u32 comp_enabled[MSM89XX_RX_MAX];
+ bool spk_boost_set;
+ bool ear_pa_boost_set;
+ bool ext_spk_boost_set;
+ bool dec_active[NUM_DECIMATORS];
+ struct on_demand_supply on_demand_list[ON_DEMAND_SUPPLIES_MAX];
+ struct regulator *spkdrv_reg;
+ /* mbhc module */
+ struct wcd_mbhc mbhc;
+ /* cal info for codec */
+ struct fw_info *fw_data;
+ struct blocking_notifier_head notifier;
+ int (*codec_spk_ext_pa_cb)(struct snd_soc_codec *codec, int enable);
+ int (*codec_hph_comp_gpio)(bool enable);
+ unsigned long status_mask;
+ struct wcd_imped_i_ref imped_i_ref;
+ enum wcd_mbhc_imp_det_pin imped_det_pin;
+};
+
+extern int msm8x16_wcd_mclk_enable(struct snd_soc_codec *codec, int mclk_enable,
+ bool dapm);
+
+extern int msm8x16_wcd_hs_detect(struct snd_soc_codec *codec,
+ struct wcd_mbhc_config *mbhc_cfg);
+
+extern void msm8x16_wcd_hs_detect_exit(struct snd_soc_codec *codec);
+
+extern void msm8x16_update_int_spk_boost(bool enable);
+
+extern void msm8x16_wcd_spk_ext_pa_cb(
+ int (*codec_spk_ext_pa)(struct snd_soc_codec *codec,
+ int enable), struct snd_soc_codec *codec);
+
+extern void msm8x16_wcd_hph_comp_cb(
+ int (*codec_hph_comp_gpio)(bool enable),
+ struct snd_soc_codec *codec);
+void enable_digital_callback(void *flag);
+void disable_digital_callback(void *flag);
+
+#endif
+
diff --git a/sound/soc/codecs/msm8x16/msm8x16_wcd_registers.h b/sound/soc/codecs/msm8x16/msm8x16_wcd_registers.h
new file mode 100644
index 000000000000..280e6f28682a
--- /dev/null
+++ b/sound/soc/codecs/msm8x16/msm8x16_wcd_registers.h
@@ -0,0 +1,585 @@
+ /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+#ifndef MSM8X16_WCD_REGISTERS_H
+#define MSM8X16_WCD_REGISTERS_H
+
+#define CDC_DIG_BASE 0xF000
+#define CDC_ANA_BASE 0xF100
+
+#define MSM89XX_PMIC_DIGITAL_REVISION1 (CDC_DIG_BASE+0x000)
+#define MSM89XX_PMIC_DIGITAL_REVISION1__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_REVISION2 (CDC_DIG_BASE+0x001)
+#define MSM89XX_PMIC_DIGITAL_REVISION2__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_PERPH_TYPE (CDC_DIG_BASE+0x004)
+#define MSM89XX_PMIC_DIGITAL_PERPH_TYPE__POR (0x23)
+#define MSM89XX_PMIC_DIGITAL_PERPH_SUBTYPE (CDC_DIG_BASE+0x005)
+#define MSM89XX_PMIC_DIGITAL_PERPH_SUBTYPE__POR (0x01)
+#define MSM89XX_PMIC_DIGITAL_INT_RT_STS (CDC_DIG_BASE+0x010)
+#define MSM89XX_PMIC_DIGITAL_INT_RT_STS__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_SET_TYPE (CDC_DIG_BASE+0x011)
+#define MSM89XX_PMIC_DIGITAL_INT_SET_TYPE__POR (0xFF)
+#define MSM89XX_PMIC_DIGITAL_INT_POLARITY_HIGH (CDC_DIG_BASE+0x012)
+#define MSM89XX_PMIC_DIGITAL_INT_POLARITY_HIGH__POR (0xFF)
+#define MSM89XX_PMIC_DIGITAL_INT_POLARITY_LOW (CDC_DIG_BASE+0x013)
+#define MSM89XX_PMIC_DIGITAL_INT_POLARITY_LOW__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_LATCHED_CLR (CDC_DIG_BASE+0x014)
+#define MSM89XX_PMIC_DIGITAL_INT_LATCHED_CLR__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_EN_SET (CDC_DIG_BASE+0x015)
+#define MSM89XX_PMIC_DIGITAL_INT_EN_SET__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_EN_CLR (CDC_DIG_BASE+0x016)
+#define MSM89XX_PMIC_DIGITAL_INT_EN_CLR__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_LATCHED_STS (CDC_DIG_BASE+0x018)
+#define MSM89XX_PMIC_DIGITAL_INT_LATCHED_STS__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_PENDING_STS (CDC_DIG_BASE+0x019)
+#define MSM89XX_PMIC_DIGITAL_INT_PENDING_STS__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_MID_SEL (CDC_DIG_BASE+0x01A)
+#define MSM89XX_PMIC_DIGITAL_INT_MID_SEL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_PRIORITY (CDC_DIG_BASE+0x01B)
+#define MSM89XX_PMIC_DIGITAL_INT_PRIORITY__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_GPIO_MODE (CDC_DIG_BASE+0x040)
+#define MSM89XX_PMIC_DIGITAL_GPIO_MODE__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_PIN_CTL_OE (CDC_DIG_BASE+0x041)
+#define MSM89XX_PMIC_DIGITAL_PIN_CTL_OE__POR (0x01)
+#define MSM89XX_PMIC_DIGITAL_PIN_CTL_DATA (CDC_DIG_BASE+0x042)
+#define MSM89XX_PMIC_DIGITAL_PIN_CTL_DATA__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_PIN_STATUS (CDC_DIG_BASE+0x043)
+#define MSM89XX_PMIC_DIGITAL_PIN_STATUS__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_HDRIVE_CTL (CDC_DIG_BASE+0x044)
+#define MSM89XX_PMIC_DIGITAL_HDRIVE_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_RST_CTL (CDC_DIG_BASE+0x046)
+#define MSM89XX_PMIC_DIGITAL_CDC_RST_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_TOP_CLK_CTL (CDC_DIG_BASE+0x048)
+#define MSM89XX_PMIC_DIGITAL_CDC_TOP_CLK_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL (CDC_DIG_BASE+0x049)
+#define MSM89XX_PMIC_DIGITAL_CDC_ANA_CLK_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL (CDC_DIG_BASE+0x04A)
+#define MSM89XX_PMIC_DIGITAL_CDC_DIG_CLK_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_TX1_CTL (CDC_DIG_BASE+0x050)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_TX1_CTL__POR (0x02)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_TX2_CTL (CDC_DIG_BASE+0x051)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_TX2_CTL__POR (0x02)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_HPHR_DAC_CTL (CDC_DIG_BASE+0x052)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_HPHR_DAC_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_RX1_CTL (CDC_DIG_BASE+0x053)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_RX1_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_RX2_CTL (CDC_DIG_BASE+0x054)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_RX2_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_RX3_CTL (CDC_DIG_BASE+0x055)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_RX3_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_RX_LB_CTL (CDC_DIG_BASE+0x056)
+#define MSM89XX_PMIC_DIGITAL_CDC_CONN_RX_LB_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_CDC_RX_CTL1 (CDC_DIG_BASE+0x058)
+#define MSM89XX_PMIC_DIGITAL_CDC_RX_CTL1__POR (0x7C)
+#define MSM89XX_PMIC_DIGITAL_CDC_RX_CTL2 (CDC_DIG_BASE+0x059)
+#define MSM89XX_PMIC_DIGITAL_CDC_RX_CTL2__POR (0x7C)
+#define MSM89XX_PMIC_DIGITAL_CDC_RX_CTL3 (CDC_DIG_BASE+0x05A)
+#define MSM89XX_PMIC_DIGITAL_CDC_RX_CTL3__POR (0x7C)
+#define MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA0 (CDC_DIG_BASE+0x05B)
+#define MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA0__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA1 (CDC_DIG_BASE+0x05C)
+#define MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA1__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA2 (CDC_DIG_BASE+0x05D)
+#define MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA2__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA3 (CDC_DIG_BASE+0x05E)
+#define MSM89XX_PMIC_DIGITAL_DEM_BYPASS_DATA3__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_DIG_DEBUG_CTL (CDC_DIG_BASE+0x068)
+#define MSM89XX_PMIC_DIGITAL_DIG_DEBUG_CTL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_DIG_DEBUG_EN (CDC_DIG_BASE+0x069)
+#define MSM89XX_PMIC_DIGITAL_DIG_DEBUG_EN__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_SPARE_0 (CDC_DIG_BASE+0x070)
+#define MSM89XX_PMIC_DIGITAL_SPARE_0__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_SPARE_1 (CDC_DIG_BASE+0x071)
+#define MSM89XX_PMIC_DIGITAL_SPARE_1__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_SPARE_2 (CDC_DIG_BASE+0x072)
+#define MSM89XX_PMIC_DIGITAL_SPARE_2__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_SEC_ACCESS (CDC_DIG_BASE+0x0D0)
+#define MSM89XX_PMIC_DIGITAL_SEC_ACCESS__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL1 (CDC_DIG_BASE+0x0D8)
+#define MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL1__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL2 (CDC_DIG_BASE+0x0D9)
+#define MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL2__POR (0x01)
+#define MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3 (CDC_DIG_BASE+0x0DA)
+#define MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL3__POR (0x05)
+#define MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL4 (CDC_DIG_BASE+0x0DB)
+#define MSM89XX_PMIC_DIGITAL_PERPH_RESET_CTL4__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_TEST1 (CDC_DIG_BASE+0x0E0)
+#define MSM89XX_PMIC_DIGITAL_INT_TEST1__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_INT_TEST_VAL (CDC_DIG_BASE+0x0E1)
+#define MSM89XX_PMIC_DIGITAL_INT_TEST_VAL__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_TRIM_NUM (CDC_DIG_BASE+0x0F0)
+#define MSM89XX_PMIC_DIGITAL_TRIM_NUM__POR (0x00)
+#define MSM89XX_PMIC_DIGITAL_TRIM_CTRL (CDC_DIG_BASE+0x0F1)
+#define MSM89XX_PMIC_DIGITAL_TRIM_CTRL__POR (0x00)
+
+#define MSM89XX_PMIC_ANALOG_REVISION1 (CDC_ANA_BASE+0x00)
+#define MSM89XX_PMIC_ANALOG_REVISION1__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_REVISION2 (CDC_ANA_BASE+0x01)
+#define MSM89XX_PMIC_ANALOG_REVISION2__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_REVISION3 (CDC_ANA_BASE+0x02)
+#define MSM89XX_PMIC_ANALOG_REVISION3__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_REVISION4 (CDC_ANA_BASE+0x03)
+#define MSM89XX_PMIC_ANALOG_REVISION4__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_PERPH_TYPE (CDC_ANA_BASE+0x04)
+#define MSM89XX_PMIC_ANALOG_PERPH_TYPE__POR (0x23)
+#define MSM89XX_PMIC_ANALOG_PERPH_SUBTYPE (CDC_ANA_BASE+0x05)
+#define MSM89XX_PMIC_ANALOG_PERPH_SUBTYPE__POR (0x09)
+#define MSM89XX_PMIC_ANALOG_INT_RT_STS (CDC_ANA_BASE+0x10)
+#define MSM89XX_PMIC_ANALOG_INT_RT_STS__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_SET_TYPE (CDC_ANA_BASE+0x11)
+#define MSM89XX_PMIC_ANALOG_INT_SET_TYPE__POR (0x3F)
+#define MSM89XX_PMIC_ANALOG_INT_POLARITY_HIGH (CDC_ANA_BASE+0x12)
+#define MSM89XX_PMIC_ANALOG_INT_POLARITY_HIGH__POR (0x3F)
+#define MSM89XX_PMIC_ANALOG_INT_POLARITY_LOW (CDC_ANA_BASE+0x13)
+#define MSM89XX_PMIC_ANALOG_INT_POLARITY_LOW__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_LATCHED_CLR (CDC_ANA_BASE+0x14)
+#define MSM89XX_PMIC_ANALOG_INT_LATCHED_CLR__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_EN_SET (CDC_ANA_BASE+0x15)
+#define MSM89XX_PMIC_ANALOG_INT_EN_SET__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_EN_CLR (CDC_ANA_BASE+0x16)
+#define MSM89XX_PMIC_ANALOG_INT_EN_CLR__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_LATCHED_STS (CDC_ANA_BASE+0x18)
+#define MSM89XX_PMIC_ANALOG_INT_LATCHED_STS__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_PENDING_STS (CDC_ANA_BASE+0x19)
+#define MSM89XX_PMIC_ANALOG_INT_PENDING_STS__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_MID_SEL (CDC_ANA_BASE+0x1A)
+#define MSM89XX_PMIC_ANALOG_INT_MID_SEL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_PRIORITY (CDC_ANA_BASE+0x1B)
+#define MSM89XX_PMIC_ANALOG_INT_PRIORITY__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_MICB_1_EN (CDC_ANA_BASE+0x40)
+#define MSM89XX_PMIC_ANALOG_MICB_1_EN__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_MICB_1_VAL (CDC_ANA_BASE+0x41)
+#define MSM89XX_PMIC_ANALOG_MICB_1_VAL__POR (0x20)
+#define MSM89XX_PMIC_ANALOG_MICB_1_CTL (CDC_ANA_BASE+0x42)
+#define MSM89XX_PMIC_ANALOG_MICB_1_CTL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_MICB_1_INT_RBIAS (CDC_ANA_BASE+0x43)
+#define MSM89XX_PMIC_ANALOG_MICB_1_INT_RBIAS__POR (0x49)
+#define MSM89XX_PMIC_ANALOG_MICB_2_EN (CDC_ANA_BASE+0x44)
+#define MSM89XX_PMIC_ANALOG_MICB_2_EN__POR (0x20)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL_2 (CDC_ANA_BASE+0x45)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL_2__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL (CDC_ANA_BASE+0x46)
+#define MSM89XX_PMIC_ANALOG_MASTER_BIAS_CTL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1 (CDC_ANA_BASE+0x47)
+#define MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_1__POR (0x35)
+#define MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2 (CDC_ANA_BASE+0x50)
+#define MSM89XX_PMIC_ANALOG_MBHC_DET_CTL_2__POR (0x08)
+#define MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL (CDC_ANA_BASE+0x51)
+#define MSM89XX_PMIC_ANALOG_MBHC_FSM_CTL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER (CDC_ANA_BASE+0x52)
+#define MSM89XX_PMIC_ANALOG_MBHC_DBNC_TIMER__POR (0x98)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL (CDC_ANA_BASE+0x53)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN0_ZDETL_CTL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN1_ZDETM_CTL (CDC_ANA_BASE+0x54)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN1_ZDETM_CTL__POR (0x20)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL (CDC_ANA_BASE+0x55)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN2_ZDETH_CTL__POR (0x40)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN3_CTL (CDC_ANA_BASE+0x56)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN3_CTL__POR (0x61)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN4_CTL (CDC_ANA_BASE+0x57)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN4_CTL__POR (0x80)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT (CDC_ANA_BASE+0x58)
+#define MSM89XX_PMIC_ANALOG_MBHC_BTN_RESULT__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT (CDC_ANA_BASE+0x59)
+#define MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_TX_1_EN (CDC_ANA_BASE+0x60)
+#define MSM89XX_PMIC_ANALOG_TX_1_EN__POR (0x03)
+#define MSM89XX_PMIC_ANALOG_TX_2_EN (CDC_ANA_BASE+0x61)
+#define MSM89XX_PMIC_ANALOG_TX_2_EN__POR (0x03)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_1 (CDC_ANA_BASE+0x62)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_1__POR (0xBF)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_2 (CDC_ANA_BASE+0x63)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_TEST_CTL_2__POR (0x8C)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL (CDC_ANA_BASE+0x64)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_ATEST_CTL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_OPAMP_BIAS (CDC_ANA_BASE+0x65)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_OPAMP_BIAS__POR (0x6B)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_TXFE_CLKDIV (CDC_ANA_BASE+0x66)
+#define MSM89XX_PMIC_ANALOG_TX_1_2_TXFE_CLKDIV__POR (0x51)
+#define MSM89XX_PMIC_ANALOG_TX_3_EN (CDC_ANA_BASE+0x67)
+#define MSM89XX_PMIC_ANALOG_TX_3_EN__POR (0x02)
+#define MSM89XX_PMIC_ANALOG_NCP_EN (CDC_ANA_BASE+0x80)
+#define MSM89XX_PMIC_ANALOG_NCP_EN__POR (0x26)
+#define MSM89XX_PMIC_ANALOG_NCP_CLK (CDC_ANA_BASE+0x81)
+#define MSM89XX_PMIC_ANALOG_NCP_CLK__POR (0x23)
+#define MSM89XX_PMIC_ANALOG_NCP_DEGLITCH (CDC_ANA_BASE+0x82)
+#define MSM89XX_PMIC_ANALOG_NCP_DEGLITCH__POR (0x5B)
+#define MSM89XX_PMIC_ANALOG_NCP_FBCTRL (CDC_ANA_BASE+0x83)
+#define MSM89XX_PMIC_ANALOG_NCP_FBCTRL__POR (0x08)
+#define MSM89XX_PMIC_ANALOG_NCP_BIAS (CDC_ANA_BASE+0x84)
+#define MSM89XX_PMIC_ANALOG_NCP_BIAS__POR (0x29)
+#define MSM89XX_PMIC_ANALOG_NCP_VCTRL (CDC_ANA_BASE+0x85)
+#define MSM89XX_PMIC_ANALOG_NCP_VCTRL__POR (0x24)
+#define MSM89XX_PMIC_ANALOG_NCP_TEST (CDC_ANA_BASE+0x86)
+#define MSM89XX_PMIC_ANALOG_NCP_TEST__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_NCP_CLIM_ADDR (CDC_ANA_BASE+0x87)
+#define MSM89XX_PMIC_ANALOG_NCP_CLIM_ADDR__POR (0xD5)
+#define MSM89XX_PMIC_ANALOG_RX_CLOCK_DIVIDER (CDC_ANA_BASE+0x90)
+#define MSM89XX_PMIC_ANALOG_RX_CLOCK_DIVIDER__POR (0xE8)
+#define MSM89XX_PMIC_ANALOG_RX_COM_OCP_CTL (CDC_ANA_BASE+0x91)
+#define MSM89XX_PMIC_ANALOG_RX_COM_OCP_CTL__POR (0xCF)
+#define MSM89XX_PMIC_ANALOG_RX_COM_OCP_COUNT (CDC_ANA_BASE+0x92)
+#define MSM89XX_PMIC_ANALOG_RX_COM_OCP_COUNT__POR (0x6E)
+#define MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC (CDC_ANA_BASE+0x93)
+#define MSM89XX_PMIC_ANALOG_RX_COM_BIAS_DAC__POR (0x18)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_PA (CDC_ANA_BASE+0x94)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_PA__POR (0x5A)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_LDO_OCP (CDC_ANA_BASE+0x95)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_LDO_OCP__POR (0x69)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_CNP (CDC_ANA_BASE+0x96)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_BIAS_CNP__POR (0x29)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN (CDC_ANA_BASE+0x97)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_CNP_EN__POR (0x80)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_CTL (CDC_ANA_BASE+0x98)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_CTL__POR (0xDA)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_TIME (CDC_ANA_BASE+0x99)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_CNP_WG_TIME__POR (0x16)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_L_TEST (CDC_ANA_BASE+0x9A)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_L_TEST__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_L_PA_DAC_CTL (CDC_ANA_BASE+0x9B)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_L_PA_DAC_CTL__POR (0x20)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_R_TEST (CDC_ANA_BASE+0x9C)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_R_TEST__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_R_PA_DAC_CTL (CDC_ANA_BASE+0x9D)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_R_PA_DAC_CTL__POR (0x20)
+#define MSM89XX_PMIC_ANALOG_RX_EAR_CTL (CDC_ANA_BASE+0x9E)
+#define MSM89XX_PMIC_ANALOG_RX_EAR_CTL___POR (0x12)
+#define MSM89XX_PMIC_ANALOG_RX_ATEST (CDC_ANA_BASE+0x9F)
+#define MSM89XX_PMIC_ANALOG_RX_ATEST__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_STATUS (CDC_ANA_BASE+0xA0)
+#define MSM89XX_PMIC_ANALOG_RX_HPH_STATUS__POR (0x0C)
+#define MSM89XX_PMIC_ANALOG_RX_EAR_STATUS (CDC_ANA_BASE+0xA1)
+#define MSM89XX_PMIC_ANALOG_RX_EAR_STATUS__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL (CDC_ANA_BASE+0xAC)
+#define MSM89XX_PMIC_ANALOG_RX_LO_DAC_CTL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_RX_LO_EN_CTL (CDC_ANA_BASE+0xAD)
+#define MSM89XX_PMIC_ANALOG_RX_RX_LO_EN_CTL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL (CDC_ANA_BASE+0xB0)
+#define MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL__POR (0x83)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_CLIP_DET (CDC_ANA_BASE+0xB1)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_CLIP_DET__POR (0x91)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL (CDC_ANA_BASE+0xB2)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL__POR (0x29)
+#define MSM89XX_PMIC_ANALOG_SPKR_ANA_BIAS_SET (CDC_ANA_BASE+0xB3)
+#define MSM89XX_PMIC_ANALOG_SPKR_ANA_BIAS_SET__POR (0x4D)
+#define MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL (CDC_ANA_BASE+0xB4)
+#define MSM89XX_PMIC_ANALOG_SPKR_OCP_CTL__POR (0xE1)
+#define MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL (CDC_ANA_BASE+0xB5)
+#define MSM89XX_PMIC_ANALOG_SPKR_PWRSTG_CTL__POR (0x1E)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_MISC (CDC_ANA_BASE+0xB6)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_MISC__POR (0xCB)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG (CDC_ANA_BASE+0xB7)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_DBG__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_CURRENT_LIMIT (CDC_ANA_BASE+0xC0)
+#define MSM89XX_PMIC_ANALOG_CURRENT_LIMIT__POR (0x02)
+#define MSM89XX_PMIC_ANALOG_OUTPUT_VOLTAGE (CDC_ANA_BASE+0xC1)
+#define MSM89XX_PMIC_ANALOG_OUTPUT_VOLTAGE__POR (0x14)
+#define MSM89XX_PMIC_ANALOG_BYPASS_MODE (CDC_ANA_BASE+0xC2)
+#define MSM89XX_PMIC_ANALOG_BYPASS_MODE__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_BOOST_EN_CTL (CDC_ANA_BASE+0xC3)
+#define MSM89XX_PMIC_ANALOG_BOOST_EN_CTL__POR (0x1F)
+#define MSM89XX_PMIC_ANALOG_SLOPE_COMP_IP_ZERO (CDC_ANA_BASE+0xC4)
+#define MSM89XX_PMIC_ANALOG_SLOPE_COMP_IP_ZERO__POR (0x8C)
+#define MSM89XX_PMIC_ANALOG_RDSON_MAX_DUTY_CYCLE (CDC_ANA_BASE+0xC5)
+#define MSM89XX_PMIC_ANALOG_RDSON_MAX_DUTY_CYCLE__POR (0xC0)
+#define MSM89XX_PMIC_ANALOG_BOOST_TEST1_1 (CDC_ANA_BASE+0xC6)
+#define MSM89XX_PMIC_ANALOG_BOOST_TEST1_1__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_BOOST_TEST_2 (CDC_ANA_BASE+0xC7)
+#define MSM89XX_PMIC_ANALOG_BOOST_TEST_2__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_SPKR_SAR_STATUS (CDC_ANA_BASE+0xC8)
+#define MSM89XX_PMIC_ANALOG_SPKR_SAR_STATUS__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_STATUS (CDC_ANA_BASE+0xC9)
+#define MSM89XX_PMIC_ANALOG_SPKR_DRV_STATUS__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_PBUS_ADD_CSR (CDC_ANA_BASE+0xCE)
+#define MSM89XX_PMIC_ANALOG_PBUS_ADD_CSR__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_PBUS_ADD_SEL (CDC_ANA_BASE+0xCF)
+#define MSM89XX_PMIC_ANALOG_PBUS_ADD_SEL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_SEC_ACCESS (CDC_ANA_BASE+0xD0)
+#define MSM89XX_PMIC_ANALOG_SEC_ACCESS__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL1 (CDC_ANA_BASE+0xD8)
+#define MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL1__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL2 (CDC_ANA_BASE+0xD9)
+#define MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL2__POR (0x01)
+#define MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3 (CDC_ANA_BASE+0xDA)
+#define MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL3__POR (0x05)
+#define MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL4 (CDC_ANA_BASE+0xDB)
+#define MSM89XX_PMIC_ANALOG_PERPH_RESET_CTL4__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_TEST1 (CDC_ANA_BASE+0xE0)
+#define MSM89XX_PMIC_ANALOG_INT_TEST1__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_INT_TEST_VAL (CDC_ANA_BASE+0xE1)
+#define MSM89XX_PMIC_ANALOG_INT_TEST_VAL__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_TRIM_NUM (CDC_ANA_BASE+0xF0)
+#define MSM89XX_PMIC_ANALOG_TRIM_NUM__POR (0x04)
+#define MSM89XX_PMIC_ANALOG_TRIM_CTRL1 (CDC_ANA_BASE+0xF1)
+#define MSM89XX_PMIC_ANALOG_TRIM_CTRL1__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_TRIM_CTRL2 (CDC_ANA_BASE+0xF2)
+#define MSM89XX_PMIC_ANALOG_TRIM_CTRL2__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_TRIM_CTRL3 (CDC_ANA_BASE+0xF3)
+#define MSM89XX_PMIC_ANALOG_TRIM_CTRL3__POR (0x00)
+#define MSM89XX_PMIC_ANALOG_TRIM_CTRL4 (CDC_ANA_BASE+0xF4)
+#define MSM89XX_PMIC_ANALOG_TRIM_CTRL4__POR (0x00)
+
+#define MSM89XX_PMIC_CDC_NUM_REGISTERS \
+ (MSM89XX_PMIC_ANALOG_TRIM_CTRL4+1)
+#define MSM89XX_PMIC_CDC_MAX_REGISTER \
+ (MSM89XX_PMIC_CDC_NUM_REGISTERS-1)
+#define MSM89XX_PMIC_CDC_CACHE_SIZE \
+ MSM89XX_PMIC_CDC_NUM_REGISTERS
+
+
+#define MSM89XX_CDC_CORE_CLK_RX_RESET_CTL (0x00)
+#define MSM89XX_CDC_CORE_CLK_RX_RESET_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_TX_RESET_B1_CTL (0x04)
+#define MSM89XX_CDC_CORE_CLK_TX_RESET_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_DMIC_B1_CTL (0x08)
+#define MSM89XX_CDC_CORE_CLK_DMIC_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_RX_I2S_CTL (0x0C)
+#define MSM89XX_CDC_CORE_CLK_RX_I2S_CTL__POR (0x13)
+#define MSM89XX_CDC_CORE_CLK_TX_I2S_CTL (0x10)
+#define MSM89XX_CDC_CORE_CLK_TX_I2S_CTL__POR (0x13)
+#define MSM89XX_CDC_CORE_CLK_OTHR_RESET_B1_CTL (0x14)
+#define MSM89XX_CDC_CORE_CLK_OTHR_RESET_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL (0x18)
+#define MSM89XX_CDC_CORE_CLK_TX_CLK_EN_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_OTHR_CTL (0x1C)
+#define MSM89XX_CDC_CORE_CLK_OTHR_CTL__POR (0x04)
+#define MSM89XX_CDC_CORE_CLK_RX_B1_CTL (0x20)
+#define MSM89XX_CDC_CORE_CLK_RX_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_MCLK_CTL (0x24)
+#define MSM89XX_CDC_CORE_CLK_MCLK_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_PDM_CTL (0x28)
+#define MSM89XX_CDC_CORE_CLK_PDM_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_SD_CTL (0x2C)
+#define MSM89XX_CDC_CORE_CLK_SD_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_WSA_VI_B1_CTL (0x30)
+#define MSM89XX_CDC_CORE_CLK_WSA_VI_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CLK_RX_B2_CTL (0x34)
+#define MSM89XX_CDC_CORE_CLK_RX_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX1_B1_CTL (0x40)
+#define MSM89XX_CDC_CORE_RX1_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX2_B1_CTL (0x60)
+#define MSM89XX_CDC_CORE_RX2_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX3_B1_CTL (0x80)
+#define MSM89XX_CDC_CORE_RX3_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX1_B2_CTL (0x44)
+#define MSM89XX_CDC_CORE_RX1_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX2_B2_CTL (0x64)
+#define MSM89XX_CDC_CORE_RX2_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX3_B2_CTL (0x84)
+#define MSM89XX_CDC_CORE_RX3_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX1_B3_CTL (0x48)
+#define MSM89XX_CDC_CORE_RX1_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX2_B3_CTL (0x68)
+#define MSM89XX_CDC_CORE_RX2_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX3_B3_CTL (0x88)
+#define MSM89XX_CDC_CORE_RX3_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX1_B4_CTL (0x4C)
+#define MSM89XX_CDC_CORE_RX1_B4_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX2_B4_CTL (0x6C)
+#define MSM89XX_CDC_CORE_RX2_B4_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX3_B4_CTL (0x8C)
+#define MSM89XX_CDC_CORE_RX3_B4_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX1_B5_CTL (0x50)
+#define MSM89XX_CDC_CORE_RX1_B5_CTL__POR (0x68)
+#define MSM89XX_CDC_CORE_RX2_B5_CTL (0x70)
+#define MSM89XX_CDC_CORE_RX2_B5_CTL__POR (0x68)
+#define MSM89XX_CDC_CORE_RX3_B5_CTL (0x90)
+#define MSM89XX_CDC_CORE_RX3_B5_CTL__POR (0x68)
+#define MSM89XX_CDC_CORE_RX1_B6_CTL (0x54)
+#define MSM89XX_CDC_CORE_RX1_B6_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX2_B6_CTL (0x74)
+#define MSM89XX_CDC_CORE_RX2_B6_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX3_B6_CTL (0x94)
+#define MSM89XX_CDC_CORE_RX3_B6_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX1_VOL_CTL_B1_CTL (0x58)
+#define MSM89XX_CDC_CORE_RX1_VOL_CTL_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX2_VOL_CTL_B1_CTL (0x78)
+#define MSM89XX_CDC_CORE_RX2_VOL_CTL_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX3_VOL_CTL_B1_CTL (0x98)
+#define MSM89XX_CDC_CORE_RX3_VOL_CTL_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX1_VOL_CTL_B2_CTL (0x5C)
+#define MSM89XX_CDC_CORE_RX1_VOL_CTL_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX2_VOL_CTL_B2_CTL (0x7C)
+#define MSM89XX_CDC_CORE_RX2_VOL_CTL_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_RX3_VOL_CTL_B2_CTL (0x9C)
+#define MSM89XX_CDC_CORE_RX3_VOL_CTL_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TOP_GAIN_UPDATE (0xA0)
+#define MSM89XX_CDC_CORE_TOP_GAIN_UPDATE__POR (0x00)
+#define MSM89XX_CDC_CORE_TOP_CTL (0xA4)
+#define MSM89XX_CDC_CORE_TOP_CTL__POR (0x01)
+#define MSM89XX_CDC_CORE_COMP0_B1_CTL (0xB0)
+#define MSM89XX_CDC_CORE_COMP0_B1_CTL__POR (0x30)
+#define MSM89XX_CDC_CORE_COMP0_B2_CTL (0xB4)
+#define MSM89XX_CDC_CORE_COMP0_B2_CTL__POR (0xB5)
+#define MSM89XX_CDC_CORE_COMP0_B3_CTL (0xB8)
+#define MSM89XX_CDC_CORE_COMP0_B3_CTL__POR (0x28)
+#define MSM89XX_CDC_CORE_COMP0_B4_CTL (0xBC)
+#define MSM89XX_CDC_CORE_COMP0_B4_CTL__POR (0x37)
+#define MSM89XX_CDC_CORE_COMP0_B5_CTL (0xC0)
+#define MSM89XX_CDC_CORE_COMP0_B5_CTL__POR (0x7F)
+#define MSM89XX_CDC_CORE_COMP0_B6_CTL (0xC4)
+#define MSM89XX_CDC_CORE_COMP0_B6_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_COMP0_SHUT_DOWN_STATUS (0xC8)
+#define MSM89XX_CDC_CORE_COMP0_SHUT_DOWN_STATUS__POR (0x03)
+#define MSM89XX_CDC_CORE_COMP0_FS_CFG (0xCC)
+#define MSM89XX_CDC_CORE_COMP0_FS_CFG__POR (0x03)
+#define MSM89XX_CDC_CORE_COMP0_DELAY_BUF_CTL (0xD0)
+#define MSM89XX_CDC_CORE_COMP0_DELAY_BUF_CTL__POR (0x02)
+#define MSM89XX_CDC_CORE_DEBUG_DESER1_CTL (0xE0)
+#define MSM89XX_CDC_CORE_DEBUG_DESER1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_DEBUG_DESER2_CTL (0xE4)
+#define MSM89XX_CDC_CORE_DEBUG_DESER2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_DEBUG_B1_CTL_CFG (0xE8)
+#define MSM89XX_CDC_CORE_DEBUG_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_DEBUG_B2_CTL_CFG (0xEC)
+#define MSM89XX_CDC_CORE_DEBUG_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_DEBUG_B3_CTL_CFG (0xF0)
+#define MSM89XX_CDC_CORE_DEBUG_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B1_CTL (0x100)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B1_CTL (0x140)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B2_CTL (0x104)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B2_CTL (0x144)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B3_CTL (0x108)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B3_CTL (0x148)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B4_CTL (0x10C)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B4_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B4_CTL (0x14C)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B4_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B5_CTL (0x110)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B5_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B5_CTL (0x150)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B5_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B6_CTL (0x114)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B6_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B6_CTL (0x154)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B6_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B7_CTL (0x118)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B7_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B7_CTL (0x158)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B7_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B8_CTL (0x11C)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_B8_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B8_CTL (0x15C)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_B8_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_CTL (0x120)
+#define MSM89XX_CDC_CORE_IIR1_CTL__POR (0x40)
+#define MSM89XX_CDC_CORE_IIR2_CTL (0x160)
+#define MSM89XX_CDC_CORE_IIR2_CTL__POR (0x40)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_TIMER_CTL (0x124)
+#define MSM89XX_CDC_CORE_IIR1_GAIN_TIMER_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_TIMER_CTL (0x164)
+#define MSM89XX_CDC_CORE_IIR2_GAIN_TIMER_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL (0x128)
+#define MSM89XX_CDC_CORE_IIR1_COEF_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_COEF_B1_CTL (0x168)
+#define MSM89XX_CDC_CORE_IIR2_COEF_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL (0x12C)
+#define MSM89XX_CDC_CORE_IIR1_COEF_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_IIR2_COEF_B2_CTL (0x16C)
+#define MSM89XX_CDC_CORE_IIR2_COEF_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_RX1_B1_CTL (0x180)
+#define MSM89XX_CDC_CORE_CONN_RX1_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_RX1_B2_CTL (0x184)
+#define MSM89XX_CDC_CORE_CONN_RX1_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_RX1_B3_CTL (0x188)
+#define MSM89XX_CDC_CORE_CONN_RX1_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_RX2_B1_CTL (0x18C)
+#define MSM89XX_CDC_CORE_CONN_RX2_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_RX2_B2_CTL (0x190)
+#define MSM89XX_CDC_CORE_CONN_RX2_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_RX2_B3_CTL (0x194)
+#define MSM89XX_CDC_CORE_CONN_RX2_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_RX3_B1_CTL (0x198)
+#define MSM89XX_CDC_CORE_CONN_RX3_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_RX3_B2_CTL (0x19C)
+#define MSM89XX_CDC_CORE_CONN_RX3_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_TX_B1_CTL (0x1A0)
+#define MSM89XX_CDC_CORE_CONN_TX_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_EQ1_B1_CTL (0x1A8)
+#define MSM89XX_CDC_CORE_CONN_EQ1_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_EQ1_B2_CTL (0x1AC)
+#define MSM89XX_CDC_CORE_CONN_EQ1_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_EQ1_B3_CTL (0x1B0)
+#define MSM89XX_CDC_CORE_CONN_EQ1_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_EQ1_B4_CTL (0x1B4)
+#define MSM89XX_CDC_CORE_CONN_EQ1_B4_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_EQ2_B1_CTL (0x1B8)
+#define MSM89XX_CDC_CORE_CONN_EQ2_B1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_EQ2_B2_CTL (0x1BC)
+#define MSM89XX_CDC_CORE_CONN_EQ2_B2_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_EQ2_B3_CTL (0x1C0)
+#define MSM89XX_CDC_CORE_CONN_EQ2_B3_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_EQ2_B4_CTL (0x1C4)
+#define MSM89XX_CDC_CORE_CONN_EQ2_B4_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_CONN_TX_I2S_SD1_CTL (0x1C8)
+#define MSM89XX_CDC_CORE_CONN_TX_I2S_SD1_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TX1_VOL_CTL_TIMER (0x280)
+#define MSM89XX_CDC_CORE_TX1_VOL_CTL_TIMER__POR (0x00)
+#define MSM89XX_CDC_CORE_TX2_VOL_CTL_TIMER (0x2A0)
+#define MSM89XX_CDC_CORE_TX2_VOL_CTL_TIMER__POR (0x00)
+#define MSM89XX_CDC_CORE_TX3_VOL_CTL_TIMER (0x2C0)
+#define MSM89XX_CDC_CORE_TX3_VOL_CTL_TIMER__POR (0x00)
+#define MSM89XX_CDC_CORE_TX4_VOL_CTL_TIMER (0x2E0)
+#define MSM89XX_CDC_CORE_TX4_VOL_CTL_TIMER__POR (0x00)
+#define MSM89XX_CDC_CORE_TX1_VOL_CTL_GAIN (0x284)
+#define MSM89XX_CDC_CORE_TX1_VOL_CTL_GAIN__POR (0x00)
+#define MSM89XX_CDC_CORE_TX2_VOL_CTL_GAIN (0x2A4)
+#define MSM89XX_CDC_CORE_TX2_VOL_CTL_GAIN__POR (0x00)
+#define MSM89XX_CDC_CORE_TX3_VOL_CTL_GAIN (0x2C4)
+#define MSM89XX_CDC_CORE_TX3_VOL_CTL_GAIN__POR (0x00)
+#define MSM89XX_CDC_CORE_TX4_VOL_CTL_GAIN (0x2E4)
+#define MSM89XX_CDC_CORE_TX4_VOL_CTL_GAIN__POR (0x00)
+#define MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG (0x288)
+#define MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG__POR (0x00)
+#define MSM89XX_CDC_CORE_TX2_VOL_CTL_CFG (0x2A8)
+#define MSM89XX_CDC_CORE_TX2_VOL_CTL_CFG__POR (0x00)
+#define MSM89XX_CDC_CORE_TX3_VOL_CTL_CFG (0x2C8)
+#define MSM89XX_CDC_CORE_TX3_VOL_CTL_CFG__POR (0x00)
+#define MSM89XX_CDC_CORE_TX4_VOL_CTL_CFG (0x2E8)
+#define MSM89XX_CDC_CORE_TX4_VOL_CTL_CFG__POR (0x00)
+#define MSM89XX_CDC_CORE_TX1_MUX_CTL (0x28C)
+#define MSM89XX_CDC_CORE_TX1_MUX_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TX2_MUX_CTL (0x2AC)
+#define MSM89XX_CDC_CORE_TX2_MUX_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TX3_MUX_CTL (0x2CC)
+#define MSM89XX_CDC_CORE_TX3_MUX_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TX4_MUX_CTL (0x2EC)
+#define MSM89XX_CDC_CORE_TX4_MUX_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TX1_CLK_FS_CTL (0x290)
+#define MSM89XX_CDC_CORE_TX1_CLK_FS_CTL__POR (0x03)
+#define MSM89XX_CDC_CORE_TX2_CLK_FS_CTL (0x2B0)
+#define MSM89XX_CDC_CORE_TX2_CLK_FS_CTL__POR (0x03)
+#define MSM89XX_CDC_CORE_TX3_CLK_FS_CTL (0x2D0)
+#define MSM89XX_CDC_CORE_TX3_CLK_FS_CTL__POR (0x03)
+#define MSM89XX_CDC_CORE_TX4_CLK_FS_CTL (0x2F0)
+#define MSM89XX_CDC_CORE_TX4_CLK_FS_CTL__POR (0x03)
+#define MSM89XX_CDC_CORE_TX1_DMIC_CTL (0x294)
+#define MSM89XX_CDC_CORE_TX1_DMIC_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TX2_DMIC_CTL (0x2B4)
+#define MSM89XX_CDC_CORE_TX2_DMIC_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TX3_DMIC_CTL (0x2D4)
+#define MSM89XX_CDC_CORE_TX3_DMIC_CTL__POR (0x00)
+#define MSM89XX_CDC_CORE_TX4_DMIC_CTL (0x2F4)
+#define MSM89XX_CDC_CORE_TX4_DMIC_CTL__POR (0x00)
+
+#define MSM89XX_CDC_CORE_NUM_REGISTERS \
+ (MSM89XX_CDC_CORE_TX4_DMIC_CTL+1)
+#define MSM89XX_CDC_CORE_MAX_REGISTER \
+ (MSM89XX_CDC_CORE_NUM_REGISTERS-1)
+#define MSM89XX_CDC_CORE_CACHE_SIZE \
+ MSM89XX_CDC_CORE_NUM_REGISTERS
+#endif
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index 11993bb9a639..e922a5a0e262 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -356,6 +356,7 @@ enum {
ANC_MIC_AMIC4,
ANC_MIC_AMIC5,
ANC_MIC_AMIC6,
+ CLASSH_CONFIG,
};
enum {
@@ -4501,6 +4502,7 @@ static int tasha_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
int hph_mode = tasha->hph_mode;
u8 dem_inp;
int ret = 0;
+ uint32_t impedl = 0, impedr = 0;
dev_dbg(codec->dev, "%s wname: %s event: %d hph_mode: %d\n", __func__,
w->name, event, hph_mode);
@@ -4534,6 +4536,16 @@ static int tasha_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
snd_soc_update_bits(codec,
WCD9335_CDC_RX1_RX_PATH_CFG0, 0x10, 0x10);
+ ret = wcd_mbhc_get_impedance(&tasha->mbhc,
+ &impedl, &impedr);
+ if (!ret) {
+ wcd_clsh_imped_config(codec, impedl, false);
+ set_bit(CLASSH_CONFIG, &tasha->status_mask);
+ } else
+ dev_dbg(codec->dev, "%s: Failed to get mbhc impedance %d\n",
+ __func__, ret);
+
+
break;
case SND_SOC_DAPM_POST_PMU:
/* 1000us required as per HW requirement */
@@ -4563,6 +4575,15 @@ static int tasha_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
WCD_CLSH_STATE_HPHL,
((hph_mode == CLS_H_LOHIFI) ?
CLS_H_HIFI : hph_mode));
+
+ if (test_bit(CLASSH_CONFIG, &tasha->status_mask)) {
+ wcd_clsh_imped_config(codec, impedl, true);
+ clear_bit(CLASSH_CONFIG, &tasha->status_mask);
+ } else
+ dev_dbg(codec->dev, "%s: Failed to get mbhc impedance %d\n",
+ __func__, ret);
+
+
break;
};
@@ -12047,7 +12068,7 @@ static const struct tasha_reg_mask_val tasha_codec_reg_init_val_2_0[] = {
{WCD9335_RCO_CTRL_2, 0x0F, 0x08},
{WCD9335_RX_BIAS_FLYB_MID_RST, 0xF0, 0x10},
{WCD9335_FLYBACK_CTRL_1, 0x20, 0x20},
- {WCD9335_HPH_OCP_CTL, 0xFF, 0x5A},
+ {WCD9335_HPH_OCP_CTL, 0xFF, 0x7A},
{WCD9335_HPH_L_TEST, 0x01, 0x01},
{WCD9335_HPH_R_TEST, 0x01, 0x01},
{WCD9335_CDC_BOOST0_BOOST_CFG1, 0x3F, 0x12},
@@ -12060,6 +12081,12 @@ static const struct tasha_reg_mask_val tasha_codec_reg_init_val_2_0[] = {
{WCD9335_CDC_RX0_RX_PATH_SEC0, 0xFC, 0xF4},
{WCD9335_HPH_REFBUFF_LP_CTL, 0x08, 0x08},
{WCD9335_HPH_REFBUFF_LP_CTL, 0x06, 0x02},
+ {WCD9335_DIFF_LO_CORE_OUT_PROG, 0xFC, 0xA0},
+ {WCD9335_SE_LO_COM1, 0xFF, 0xC0},
+ {WCD9335_CDC_RX3_RX_PATH_SEC0, 0xFC, 0xF4},
+ {WCD9335_CDC_RX4_RX_PATH_SEC0, 0xFC, 0xF4},
+ {WCD9335_CDC_RX5_RX_PATH_SEC0, 0xFC, 0xF8},
+ {WCD9335_CDC_RX6_RX_PATH_SEC0, 0xFC, 0xF8},
};
static const struct tasha_reg_mask_val tasha_codec_reg_defaults[] = {
@@ -12094,7 +12121,6 @@ static const struct tasha_reg_mask_val tasha_codec_reg_init_common_val[] = {
{WCD9335_CDC_RX8_RX_PATH_CFG1, 0x08, 0x08},
{WCD9335_ANA_LO_1_2, 0x3C, 0X3C},
{WCD9335_DIFF_LO_COM_SWCAP_REFBUF_FREQ, 0x70, 0x00},
- {WCD9335_DIFF_LO_COM_PA_FREQ, 0x70, 0x40},
{WCD9335_SOC_MAD_AUDIO_CTL_2, 0x03, 0x03},
{WCD9335_CDC_TOP_TOP_CFG1, 0x02, 0x02},
{WCD9335_CDC_TOP_TOP_CFG1, 0x01, 0x01},
@@ -12188,6 +12214,7 @@ static const struct tasha_reg_mask_val tasha_codec_reg_init_1_x_val[] = {
{WCD9335_DIFF_LO_CORE_OUT_PROG, 0xFC, 0xD8},
{WCD9335_CDC_RX5_RX_PATH_SEC3, 0xBD, 0xBD},
{WCD9335_CDC_RX6_RX_PATH_SEC3, 0xBD, 0xBD},
+ {WCD9335_DIFF_LO_COM_PA_FREQ, 0x70, 0x40},
};
static void tasha_update_reg_reset_values(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wcd9xxx-common-v2.c b/sound/soc/codecs/wcd9xxx-common-v2.c
index 5d4ac1f99de0..615922274690 100644
--- a/sound/soc/codecs/wcd9xxx-common-v2.c
+++ b/sound/soc/codecs/wcd9xxx-common-v2.c
@@ -21,6 +21,7 @@
#include "wcd9xxx-common-v2.h"
#define WCD_USLEEP_RANGE 50
+#define MAX_IMPED_PARAMS 6
enum {
DAC_GAIN_0DB = 0,
@@ -49,10 +50,161 @@ enum {
DELTA_I_50MA,
};
+struct wcd_imped_val {
+ u32 imped_val;
+ u8 index;
+};
+
+static const struct wcd_reg_mask_val imped_table[][MAX_IMPED_PARAMS] = {
+ {
+ {WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xf5},
+ {WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xf5},
+ {WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x01},
+ {WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xf5},
+ {WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xf5},
+ {WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x01},
+ },
+ {
+ {WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xf7},
+ {WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xf7},
+ {WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x01},
+ {WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xf7},
+ {WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xf7},
+ {WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x01},
+ },
+ {
+ {WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xf9},
+ {WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xf9},
+ {WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x0},
+ {WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xf9},
+ {WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xf9},
+ {WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x0},
+ },
+ {
+ {WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xfa},
+ {WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xfa},
+ {WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x01},
+ {WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xfa},
+ {WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xfa},
+ {WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x01},
+ },
+ {
+ {WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xfb},
+ {WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xfb},
+ {WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x01},
+ {WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xfb},
+ {WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xfb},
+ {WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x01},
+ },
+ {
+ {WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xfc},
+ {WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xfc},
+ {WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x01},
+ {WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xfc},
+ {WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xfc},
+ {WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x01},
+ },
+ {
+ {WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xfd},
+ {WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xfd},
+ {WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x01},
+ {WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xfd},
+ {WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xfd},
+ {WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x01},
+ },
+ {
+ {WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xfe},
+ {WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xfe},
+ {WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x01},
+ {WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xfe},
+ {WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xfe},
+ {WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x01},
+ },
+ {
+ {WCD9XXX_CDC_RX1_RX_VOL_CTL, 0xff, 0xff},
+ {WCD9XXX_CDC_RX1_RX_VOL_MIX_CTL, 0xff, 0xff},
+ {WCD9XXX_CDC_RX1_RX_PATH_SEC1, 0x01, 0x00},
+ {WCD9XXX_CDC_RX2_RX_VOL_CTL, 0xff, 0xff},
+ {WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL, 0xff, 0xff},
+ {WCD9XXX_CDC_RX2_RX_PATH_SEC1, 0x01, 0x00},
+ },
+};
+
+static const struct wcd_imped_val imped_index[] = {
+ {4, 0},
+ {5, 1},
+ {6, 2},
+ {7, 3},
+ {8, 4},
+ {9, 5},
+ {10, 6},
+ {11, 7},
+ {12, 8},
+ {13, 9},
+};
+
static void (*clsh_state_fp[NUM_CLSH_STATES_V2])(struct snd_soc_codec *,
struct wcd_clsh_cdc_data *,
u8 req_state, bool en, int mode);
+static int get_impedance_index(int imped)
+{
+ int i = 0;
+
+ if (imped < imped_index[i].imped_val) {
+ pr_debug("%s, detected impedance is less than 4 Ohm\n",
+ __func__);
+ i = 0;
+ goto ret;
+ }
+ if (imped >= imped_index[ARRAY_SIZE(imped_index) - 1].imped_val) {
+ pr_debug("%s, detected impedance is greater than 12 Ohm\n",
+ __func__);
+ i = ARRAY_SIZE(imped_index) - 1;
+ goto ret;
+ }
+ for (i = 0; i < ARRAY_SIZE(imped_index) - 1; i++) {
+ if (imped >= imped_index[i].imped_val &&
+ imped < imped_index[i + 1].imped_val)
+ break;
+ }
+ret:
+ pr_debug("%s: selected impedance index = %d\n",
+ __func__, imped_index[i].index);
+ return imped_index[i].index;
+}
+
+/*
+ * Function: wcd_clsh_imped_config
+ * Params: codec, imped, reset
+ * Description:
+ * This function updates HPHL and HPHR gain settings
+ * according to the impedance value.
+ */
+void wcd_clsh_imped_config(struct snd_soc_codec *codec, int imped, bool reset)
+{
+ int i;
+ int index = 0;
+
+ /* reset = 1, which means request is to reset the register values */
+ if (reset) {
+ for (i = 0; i < MAX_IMPED_PARAMS; i++)
+ snd_soc_update_bits(codec, imped_table[index][i].reg,
+ imped_table[index][i].mask, 0);
+ return;
+ }
+ index = get_impedance_index(imped);
+ if (index >= (ARRAY_SIZE(imped_index) - 1)) {
+ pr_debug("%s, impedance not in range = %d\n", __func__, imped);
+ return;
+ }
+ for (i = 0; i < MAX_IMPED_PARAMS; i++)
+ snd_soc_update_bits(codec, imped_table[index][i].reg,
+ imped_table[index][i].mask,
+ imped_table[index][i].val);
+}
+EXPORT_SYMBOL(wcd_clsh_imped_config);
+
static bool is_native_44_1_active(struct snd_soc_codec *codec)
{
bool native_active = false;
@@ -338,6 +490,22 @@ static void wcd_clsh_set_hph_mode(struct snd_soc_codec *codec,
}
}
+static void wcd_clsh_set_flyback_vneg_ctl(struct snd_soc_codec *codec,
+ bool enable)
+{
+ if (enable) {
+ snd_soc_update_bits(codec, WCD9XXX_FLYBACK_VNEG_CTRL_1, 0xE0,
+ 0x00);
+ snd_soc_update_bits(codec, WCD9XXX_FLYBACK_VNEGDAC_CTRL_2,
+ 0xE0, (0x07 << 5));
+ } else {
+ snd_soc_update_bits(codec, WCD9XXX_FLYBACK_VNEG_CTRL_1, 0xE0,
+ (0x07 << 5));
+ snd_soc_update_bits(codec, WCD9XXX_FLYBACK_VNEGDAC_CTRL_2,
+ 0xE0, (0x02 << 5));
+ }
+}
+
static void wcd_clsh_set_flyback_current(struct snd_soc_codec *codec, int mode)
{
struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
@@ -373,6 +541,7 @@ static void wcd_clsh_state_lo(struct snd_soc_codec *codec,
if (is_enable) {
wcd_clsh_set_buck_regulator_mode(codec, mode);
+ wcd_clsh_set_flyback_vneg_ctl(codec, true);
wcd_clsh_set_buck_mode(codec, mode);
wcd_clsh_set_flyback_mode(codec, mode);
wcd_clsh_flyback_ctrl(codec, clsh_d, mode, true);
@@ -383,6 +552,7 @@ static void wcd_clsh_state_lo(struct snd_soc_codec *codec,
wcd_clsh_flyback_ctrl(codec, clsh_d, mode, false);
wcd_clsh_set_flyback_mode(codec, CLS_H_NORMAL);
wcd_clsh_set_buck_mode(codec, CLS_H_NORMAL);
+ wcd_clsh_set_flyback_vneg_ctl(codec, false);
wcd_clsh_set_buck_regulator_mode(codec, CLS_H_NORMAL);
}
}
@@ -562,6 +732,7 @@ static void wcd_clsh_state_hph_lo(struct snd_soc_codec *codec,
WCD9XXX_A_CDC_CLSH_K1_LSB,
0xFF, 0xC0);
wcd_clsh_set_flyback_mode(codec, mode);
+ wcd_clsh_set_flyback_vneg_ctl(codec, false);
wcd_clsh_set_buck_mode(codec, mode);
wcd_clsh_set_hph_mode(codec, mode);
wcd_clsh_set_gain_path(codec, mode);
@@ -597,6 +768,7 @@ static void wcd_clsh_state_hph_lo(struct snd_soc_codec *codec,
if ((clsh_d->state & WCD_CLSH_STATE_HPH_ST)
!= WCD_CLSH_STATE_HPH_ST) {
wcd_enable_clsh_block(codec, clsh_d, false);
+ wcd_clsh_set_flyback_vneg_ctl(codec, true);
wcd_clsh_set_flyback_mode(codec, CLS_H_NORMAL);
wcd_clsh_set_buck_mode(codec, CLS_H_NORMAL);
}
diff --git a/sound/soc/codecs/wcd9xxx-common-v2.h b/sound/soc/codecs/wcd9xxx-common-v2.h
index 2ad91189d3cb..d3c52e73a7da 100644
--- a/sound/soc/codecs/wcd9xxx-common-v2.h
+++ b/sound/soc/codecs/wcd9xxx-common-v2.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -136,6 +136,12 @@ struct vbat_monitor_reg {
u32 writes[MAX_VBAT_MONITOR_WRITES];
} __packed;
+struct wcd_reg_mask_val {
+ u16 reg;
+ u8 mask;
+ u8 val;
+};
+
extern void wcd_clsh_fsm(struct snd_soc_codec *codec,
struct wcd_clsh_cdc_data *cdc_clsh_d,
u8 clsh_event, u8 req_state,
@@ -143,6 +149,8 @@ extern void wcd_clsh_fsm(struct snd_soc_codec *codec,
extern void wcd_clsh_init(struct wcd_clsh_cdc_data *clsh);
extern int wcd_clsh_get_clsh_state(struct wcd_clsh_cdc_data *clsh);
+extern void wcd_clsh_imped_config(struct snd_soc_codec *codec, int imped,
+ bool reset);
enum {
RESERVED = 0,
diff --git a/sound/soc/msm/msmcobalt.c b/sound/soc/msm/msmcobalt.c
index 945250babf2d..763854061966 100644
--- a/sound/soc/msm/msmcobalt.c
+++ b/sound/soc/msm/msmcobalt.c
@@ -174,7 +174,7 @@ static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE"};
static char const *slim_sample_rate_text[] = {"KHZ_8", "KHZ_16",
"KHZ_32", "KHZ_44P1", "KHZ_48",
"KHZ_96", "KHZ_192"};
-static char const *bt_sco_sample_rate_text[] = {"KHZ_8", "KHZ_16"};
+static char const *bt_sample_rate_text[] = {"KHZ_8", "KHZ_16", "KHZ_48"};
static const char *const usb_ch_text[] = {"One", "Two"};
static char const *ch_text[] = {"Two", "Three", "Four", "Five",
"Six", "Seven", "Eight"};
@@ -206,7 +206,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_sample_rate, slim_sample_rate_text);
-static SOC_ENUM_SINGLE_EXT_DECL(bt_sco_sample_rate, bt_sco_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_sample_rate, usb_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_sample_rate, usb_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(hdmi_rx_sample_rate, hdmi_rx_sample_rate_text);
@@ -611,29 +611,44 @@ static int msm_vi_feed_tx_ch_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static int msm_bt_sco_sample_rate_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int msm_bt_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
/*
* Slimbus_7_Rx/Tx sample rate values should always be in sync (same)
* when used for BT_SCO use case. Return either Rx or Tx sample rate
* value.
*/
- ucontrol->value.integer.value[0] = slim_rx_cfg[SLIM_RX_7].sample_rate;
+ switch (slim_rx_cfg[SLIM_RX_7].sample_rate) {
+ case SAMPLING_RATE_48KHZ:
+ ucontrol->value.integer.value[0] = 2;
+ break;
+ case SAMPLING_RATE_16KHZ:
+ ucontrol->value.integer.value[0] = 1;
+ break;
+ case SAMPLING_RATE_8KHZ:
+ default:
+ ucontrol->value.integer.value[0] = 0;
+ break;
+ }
pr_debug("%s: sample rate = %d", __func__,
slim_rx_cfg[SLIM_RX_7].sample_rate);
return 0;
}
-static int msm_bt_sco_sample_rate_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int msm_bt_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
switch (ucontrol->value.integer.value[0]) {
case 1:
slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_16KHZ;
slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_16KHZ;
break;
+ case 2:
+ slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_48KHZ;
+ slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_48KHZ;
+ break;
case 0:
default:
slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_8KHZ;
@@ -1134,9 +1149,9 @@ static const struct snd_kcontrol_new msm_snd_controls[] = {
slim_rx_sample_rate_get, slim_rx_sample_rate_put),
SOC_ENUM_EXT("SLIM_6_RX SampleRate", slim_6_rx_sample_rate,
slim_rx_sample_rate_get, slim_rx_sample_rate_put),
- SOC_ENUM_EXT("BT_SCO SampleRate", bt_sco_sample_rate,
- msm_bt_sco_sample_rate_get,
- msm_bt_sco_sample_rate_put),
+ SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
+ msm_bt_sample_rate_get,
+ msm_bt_sample_rate_put),
SOC_ENUM_EXT("USB_AUDIO_RX SampleRate", usb_rx_sample_rate,
usb_audio_rx_sample_rate_get,
usb_audio_rx_sample_rate_put),
@@ -1341,6 +1356,8 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
break;
case MSM_BACKEND_DAI_SLIMBUS_7_RX:
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ slim_rx_cfg[SLIM_RX_7].bit_format);
rate->min = rate->max = slim_rx_cfg[SLIM_RX_7].sample_rate;
channels->min = channels->max =
slim_rx_cfg[SLIM_RX_7].channels;
@@ -3131,7 +3148,11 @@ static struct snd_soc_dai_link msm_wcn_be_dai_links[] = {
.cpu_dai_name = "msm-dai-q6-dev.16398",
.platform_name = "msm-pcm-routing",
.codec_name = "btfmslim_slave",
- .codec_dai_name = "btfm_bt_sco_slim_rx",
+ /* BT codec driver determines capabilities based on
+ * dai name, bt codecdai name should always contains
+ * supported usecase information
+ */
+ .codec_dai_name = "btfm_bt_sco_a2dp_slim_rx",
.no_pcm = 1,
.dpcm_playback = 1,
.be_id = MSM_BACKEND_DAI_SLIMBUS_7_RX,
@@ -3950,8 +3971,6 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
goto err;
}
- spdev = pdev;
-
ret = msm_populate_dai_link_component_of_node(card);
if (ret) {
ret = -EPROBE_DEFER;
@@ -3989,6 +4008,7 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
goto err;
}
dev_info(&pdev->dev, "Sound card %s registered\n", card->name);
+ spdev = pdev;
ret = of_property_read_string(pdev->dev.of_node,
"qcom,mbhc-audio-jack-type", &mbhc_audio_jack_type);
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 7684d27d60a0..c439c5cf2de5 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -37,6 +37,14 @@
#define CHANNEL_STATUS_MASK 0x4
#define AFE_API_VERSION_CLOCK_SET 1
+enum {
+ ENC_FMT_NONE,
+ ENC_FMT_SBC = ASM_MEDIA_FMT_SBC,
+ ENC_FMT_AAC_V2 = ASM_MEDIA_FMT_AAC_V2,
+ ENC_FMT_APTX = ASM_MEDIA_FMT_APTX,
+ ENC_FMT_APTX_HD = ASM_MEDIA_FMT_APTX_HD,
+};
+
static const struct afe_clk_set lpass_clk_set_default = {
AFE_API_VERSION_CLOCK_SET,
Q6AFE_LPASS_CLK_ID_PRI_PCM_IBIT,
@@ -157,6 +165,8 @@ struct msm_dai_q6_dai_data {
u32 channels;
u32 bitwidth;
u32 cal_mode;
+ u32 afe_in_channels;
+ struct afe_enc_config enc_config;
union afe_port_config port_config;
};
@@ -1330,9 +1340,20 @@ static int msm_dai_q6_prepare(struct snd_pcm_substream *substream,
int rc = 0;
if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
- rc = afe_port_start(dai->id, &dai_data->port_config,
- dai_data->rate);
-
+ if (dai_data->enc_config.format != ENC_FMT_NONE) {
+ pr_debug("%s: calling AFE_PORT_START_V2 with enc_format: %d\n",
+ __func__, dai_data->enc_config.format);
+ rc = afe_port_start_v2(dai->id, &dai_data->port_config,
+ dai_data->rate,
+ dai_data->afe_in_channels,
+ &dai_data->enc_config);
+ if (rc < 0)
+ pr_err("%s: afe_port_start_v2 failed error: %d\n",
+ __func__, rc);
+ } else {
+ rc = afe_port_start(dai->id, &dai_data->port_config,
+ dai_data->rate);
+ }
if (IS_ERR_VALUE(rc))
dev_err(dai->dev, "fail to open AFE port 0x%x\n",
dai->id);
@@ -1941,6 +1962,151 @@ static int msm_dai_q6_usb_audio_cfg_get(struct snd_kcontrol *kcontrol,
return 0;
}
+static int msm_dai_q6_afe_enc_cfg_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+ uinfo->count = sizeof(struct afe_enc_config);
+
+ return 0;
+}
+
+static int msm_dai_q6_afe_enc_cfg_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ret = 0;
+ struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+ if (dai_data) {
+ int format_size = sizeof(dai_data->enc_config.format);
+
+ pr_debug("%s:encoder config for %d format\n",
+ __func__, dai_data->enc_config.format);
+ memcpy(ucontrol->value.bytes.data,
+ &dai_data->enc_config.format,
+ format_size);
+ switch (dai_data->enc_config.format) {
+ case ENC_FMT_SBC:
+ memcpy(ucontrol->value.bytes.data + format_size,
+ &dai_data->enc_config.data,
+ sizeof(struct asm_sbc_enc_cfg_t));
+ break;
+ case ENC_FMT_AAC_V2:
+ memcpy(ucontrol->value.bytes.data + format_size,
+ &dai_data->enc_config.data,
+ sizeof(struct asm_aac_enc_cfg_v2_t));
+ break;
+ case ENC_FMT_APTX:
+ case ENC_FMT_APTX_HD:
+ memcpy(ucontrol->value.bytes.data + format_size,
+ &dai_data->enc_config.data,
+ sizeof(struct asm_aac_enc_cfg_v2_t));
+ break;
+ default:
+ pr_debug("%s: unknown format = %d\n",
+ __func__, dai_data->enc_config.format);
+ ret = -EINVAL;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int msm_dai_q6_afe_enc_cfg_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ret = 0;
+ struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+ if (dai_data) {
+ int format_size = sizeof(dai_data->enc_config.format);
+
+ memset(&dai_data->enc_config, 0x0,
+ sizeof(struct afe_enc_config));
+ memcpy(&dai_data->enc_config.format,
+ ucontrol->value.bytes.data,
+ format_size);
+ pr_debug("%s: Received encoder config for %d format\n",
+ __func__, dai_data->enc_config.format);
+ switch (dai_data->enc_config.format) {
+ case ENC_FMT_SBC:
+ memcpy(&dai_data->enc_config.data,
+ ucontrol->value.bytes.data + format_size,
+ sizeof(struct asm_sbc_enc_cfg_t));
+ break;
+ case ENC_FMT_AAC_V2:
+ memcpy(&dai_data->enc_config.data,
+ ucontrol->value.bytes.data + format_size,
+ sizeof(struct asm_aac_enc_cfg_v2_t));
+ break;
+ case ENC_FMT_APTX:
+ case ENC_FMT_APTX_HD:
+ memcpy(&dai_data->enc_config.data,
+ ucontrol->value.bytes.data + format_size,
+ sizeof(struct asm_custom_enc_cfg_aptx_t));
+ break;
+ default:
+ pr_debug("%s: Ignore enc config for unknown format = %d\n",
+ __func__, dai_data->enc_config.format);
+ ret = -EINVAL;
+ break;
+ }
+ } else
+ ret = -EINVAL;
+
+ return ret;
+}
+
+static const char *const afe_input_chs_text[] = {"Zero", "One", "Two"};
+
+static const struct soc_enum afe_input_chs_enum[] = {
+ SOC_ENUM_SINGLE_EXT(3, afe_input_chs_text),
+};
+
+static int msm_dai_q6_afe_input_channel_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+ if (dai_data) {
+ ucontrol->value.integer.value[0] = dai_data->afe_in_channels;
+ pr_debug("%s:afe input channel = %d\n",
+ __func__, dai_data->afe_in_channels);
+ }
+
+ return 0;
+}
+
+static int msm_dai_q6_afe_input_channel_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+ if (dai_data) {
+ dai_data->afe_in_channels = ucontrol->value.integer.value[0];
+ pr_debug("%s: updating afe input channel : %d\n",
+ __func__, dai_data->afe_in_channels);
+ }
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new afe_enc_config_controls[] = {
+ {
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE),
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "SLIM_7_RX Encoder Config",
+ .info = msm_dai_q6_afe_enc_cfg_info,
+ .get = msm_dai_q6_afe_enc_cfg_get,
+ .put = msm_dai_q6_afe_enc_cfg_put,
+ },
+ SOC_ENUM_EXT("AFE Input Channels", afe_input_chs_enum[0],
+ msm_dai_q6_afe_input_channel_get,
+ msm_dai_q6_afe_input_channel_put),
+};
+
static const char * const afe_cal_mode_text[] = {
"CAL_MODE_DEFAULT", "CAL_MODE_NONE"
};
@@ -2020,6 +2186,17 @@ static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
snd_ctl_new1(&sb_config_controls[1],
dai_data));
break;
+ case SLIMBUS_7_RX:
+ rc = snd_ctl_add(dai->component->card->snd_card,
+ snd_ctl_new1(&afe_enc_config_controls[0],
+ dai_data));
+ rc = snd_ctl_add(dai->component->card->snd_card,
+ snd_ctl_new1(&afe_enc_config_controls[1],
+ dai_data));
+ rc = snd_ctl_add(dai->component->card->snd_card,
+ snd_ctl_new1(&afe_enc_config_controls[2],
+ dai_data));
+ break;
case RT_PROXY_DAI_001_RX:
rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&rt_proxy_config_controls[0],
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 8ca9bb7b2ad8..9e3d85b807aa 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -244,205 +244,209 @@ static void msm_pcm_routng_cfg_matrix_map_pp(struct route_payload payload,
#define SLIMBUS_EXTPROC_RX AFE_PORT_INVALID
struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
- { PRIMARY_I2S_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_PRI_I2S_RX},
- { PRIMARY_I2S_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_PRI_I2S_TX},
- { SLIMBUS_0_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_RX},
- { SLIMBUS_0_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_TX},
- { HDMI_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_HDMI},
- { INT_BT_SCO_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_RX},
- { INT_BT_SCO_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_TX},
- { INT_FM_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_FM_RX},
- { INT_FM_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_FM_TX},
- { RT_PROXY_PORT_001_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_AFE_PCM_RX},
- { RT_PROXY_PORT_001_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_AFE_PCM_TX},
- { AFE_PORT_ID_PRIMARY_PCM_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_AUXPCM_RX},
- { AFE_PORT_ID_PRIMARY_PCM_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_AUXPCM_TX},
- { VOICE_PLAYBACK_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_VOICE_PLAYBACK_TX},
- { VOICE2_PLAYBACK_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_VOICE2_PLAYBACK_TX},
- { VOICE_RECORD_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INCALL_RECORD_RX},
- { VOICE_RECORD_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INCALL_RECORD_TX},
- { MI2S_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_MI2S_RX},
- { MI2S_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_MI2S_TX},
- { SECONDARY_I2S_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SEC_I2S_RX},
- { SLIMBUS_1_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_RX},
- { SLIMBUS_1_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_TX},
- { SLIMBUS_4_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_RX},
- { SLIMBUS_4_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_TX},
- { SLIMBUS_3_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_RX},
- { SLIMBUS_3_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_TX},
- { SLIMBUS_5_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_TX},
- { SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_STUB_RX},
- { SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_STUB_TX},
- { SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_STUB_1_TX},
- { AFE_PORT_ID_QUATERNARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0,
+ { PRIMARY_I2S_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_PRI_I2S_RX},
+ { PRIMARY_I2S_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_PRI_I2S_TX},
+ { SLIMBUS_0_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_RX},
+ { SLIMBUS_0_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_TX},
+ { HDMI_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_HDMI},
+ { INT_BT_SCO_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_RX},
+ { INT_BT_SCO_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_TX},
+ { INT_FM_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_FM_RX},
+ { INT_FM_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_FM_TX},
+ { RT_PROXY_PORT_001_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_AFE_PCM_RX},
+ { RT_PROXY_PORT_001_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_AFE_PCM_TX},
+ { AFE_PORT_ID_PRIMARY_PCM_RX, 0, 0, 0, 0, 0, 0, 0, 0,
+ LPASS_BE_AUXPCM_RX},
+ { AFE_PORT_ID_PRIMARY_PCM_TX, 0, 0, 0, 0, 0, 0, 0, 0,
+ LPASS_BE_AUXPCM_TX},
+ { VOICE_PLAYBACK_TX, 0, 0, 0, 0, 0, 0, 0, 0,
+ LPASS_BE_VOICE_PLAYBACK_TX},
+ { VOICE2_PLAYBACK_TX, 0, 0, 0, 0, 0, 0, 0, 0,
+ LPASS_BE_VOICE2_PLAYBACK_TX},
+ { VOICE_RECORD_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INCALL_RECORD_RX},
+ { VOICE_RECORD_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INCALL_RECORD_TX},
+ { MI2S_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_MI2S_RX},
+ { MI2S_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_MI2S_TX},
+ { SECONDARY_I2S_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SEC_I2S_RX},
+ { SLIMBUS_1_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_RX},
+ { SLIMBUS_1_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_TX},
+ { SLIMBUS_4_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_RX},
+ { SLIMBUS_4_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_TX},
+ { SLIMBUS_3_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_RX},
+ { SLIMBUS_3_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_TX},
+ { SLIMBUS_5_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_TX},
+ { SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_STUB_RX},
+ { SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_STUB_TX},
+ { SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_STUB_1_TX},
+ { AFE_PORT_ID_QUATERNARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_MI2S_RX},
- { AFE_PORT_ID_QUATERNARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_MI2S_TX},
- { AFE_PORT_ID_SECONDARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_MI2S_RX},
- { AFE_PORT_ID_SECONDARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_MI2S_TX},
- { AFE_PORT_ID_PRIMARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_MI2S_RX},
- { AFE_PORT_ID_PRIMARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_MI2S_TX},
- { AFE_PORT_ID_TERTIARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_MI2S_RX},
- { AFE_PORT_ID_TERTIARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_MI2S_TX},
- { AUDIO_PORT_ID_I2S_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AUDIO_PORT_ID_I2S_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_AUDIO_I2S_RX},
- { AFE_PORT_ID_SECONDARY_PCM_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_PCM_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_AUXPCM_RX},
- { AFE_PORT_ID_SECONDARY_PCM_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_PCM_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_AUXPCM_TX},
- { SLIMBUS_6_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_RX},
- { SLIMBUS_6_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_TX},
- { AFE_PORT_ID_SPDIF_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SPDIF_RX},
- { AFE_PORT_ID_SECONDARY_MI2S_RX_SD1, 0, 0, 0, 0, 0, 0, 0,
+ { SLIMBUS_6_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_RX},
+ { SLIMBUS_6_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_TX},
+ { AFE_PORT_ID_SPDIF_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SPDIF_RX},
+ { AFE_PORT_ID_SECONDARY_MI2S_RX_SD1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_MI2S_RX_SD1},
- { SLIMBUS_5_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_RX},
- { AFE_PORT_ID_QUINARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0,
+ { SLIMBUS_5_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_RX},
+ { AFE_PORT_ID_QUINARY_MI2S_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUIN_MI2S_RX},
- { AFE_PORT_ID_QUINARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUINARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUIN_MI2S_TX},
- { AFE_PORT_ID_SENARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SENARY_MI2S_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SENARY_MI2S_TX},
- { AFE_PORT_ID_PRIMARY_TDM_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_RX_0},
- { AFE_PORT_ID_PRIMARY_TDM_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_TX_0},
- { AFE_PORT_ID_PRIMARY_TDM_RX_1, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_RX_1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_RX_1},
- { AFE_PORT_ID_PRIMARY_TDM_TX_1, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_TX_1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_TX_1},
- { AFE_PORT_ID_PRIMARY_TDM_RX_2, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_RX_2, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_RX_2},
- { AFE_PORT_ID_PRIMARY_TDM_TX_2, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_TX_2, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_TX_2},
- { AFE_PORT_ID_PRIMARY_TDM_RX_3, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_RX_3, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_RX_3},
- { AFE_PORT_ID_PRIMARY_TDM_TX_3, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_TX_3, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_TX_3},
- { AFE_PORT_ID_PRIMARY_TDM_RX_4, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_RX_4, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_RX_4},
- { AFE_PORT_ID_PRIMARY_TDM_TX_4, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_TX_4, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_TX_4},
- { AFE_PORT_ID_PRIMARY_TDM_RX_5, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_RX_5, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_RX_5},
- { AFE_PORT_ID_PRIMARY_TDM_TX_5, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_TX_5, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_TX_5},
- { AFE_PORT_ID_PRIMARY_TDM_RX_6, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_RX_6, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_RX_6},
- { AFE_PORT_ID_PRIMARY_TDM_TX_6, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_TX_6, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_TX_6},
- { AFE_PORT_ID_PRIMARY_TDM_RX_7, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_RX_7, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_RX_7},
- { AFE_PORT_ID_PRIMARY_TDM_TX_7, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_PRIMARY_TDM_TX_7, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_PRI_TDM_TX_7},
- { AFE_PORT_ID_SECONDARY_TDM_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_RX_0},
- { AFE_PORT_ID_SECONDARY_TDM_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_TX_0},
- { AFE_PORT_ID_SECONDARY_TDM_RX_1, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_RX_1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_RX_1},
- { AFE_PORT_ID_SECONDARY_TDM_TX_1, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_TX_1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_TX_1},
- { AFE_PORT_ID_SECONDARY_TDM_RX_2, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_RX_2, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_RX_2},
- { AFE_PORT_ID_SECONDARY_TDM_TX_2, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_TX_2, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_TX_2},
- { AFE_PORT_ID_SECONDARY_TDM_RX_3, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_RX_3, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_RX_3},
- { AFE_PORT_ID_SECONDARY_TDM_TX_3, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_TX_3, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_TX_3},
- { AFE_PORT_ID_SECONDARY_TDM_RX_4, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_RX_4, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_RX_4},
- { AFE_PORT_ID_SECONDARY_TDM_TX_4, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_TX_4, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_TX_4},
- { AFE_PORT_ID_SECONDARY_TDM_RX_5, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_RX_5, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_RX_5},
- { AFE_PORT_ID_SECONDARY_TDM_TX_5, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_TX_5, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_TX_5},
- { AFE_PORT_ID_SECONDARY_TDM_RX_6, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_RX_6, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_RX_6},
- { AFE_PORT_ID_SECONDARY_TDM_TX_6, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_TX_6, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_TX_6},
- { AFE_PORT_ID_SECONDARY_TDM_RX_7, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_RX_7, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_RX_7},
- { AFE_PORT_ID_SECONDARY_TDM_TX_7, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_SECONDARY_TDM_TX_7, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_SEC_TDM_TX_7},
- { AFE_PORT_ID_TERTIARY_TDM_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_RX_0},
- { AFE_PORT_ID_TERTIARY_TDM_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_TX_0},
- { AFE_PORT_ID_TERTIARY_TDM_RX_1, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_RX_1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_RX_1},
- { AFE_PORT_ID_TERTIARY_TDM_TX_1, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_TX_1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_TX_1},
- { AFE_PORT_ID_TERTIARY_TDM_RX_2, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_RX_2, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_RX_2},
- { AFE_PORT_ID_TERTIARY_TDM_TX_2, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_TX_2, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_TX_2},
- { AFE_PORT_ID_TERTIARY_TDM_RX_3, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_RX_3, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_RX_3},
- { AFE_PORT_ID_TERTIARY_TDM_TX_3, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_TX_3, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_TX_3},
- { AFE_PORT_ID_TERTIARY_TDM_RX_4, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_RX_4, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_RX_4},
- { AFE_PORT_ID_TERTIARY_TDM_TX_4, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_TX_4, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_TX_4},
- { AFE_PORT_ID_TERTIARY_TDM_RX_5, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_RX_5, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_RX_5},
- { AFE_PORT_ID_TERTIARY_TDM_TX_5, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_TX_5, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_TX_5},
- { AFE_PORT_ID_TERTIARY_TDM_RX_6, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_RX_6, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_RX_6},
- { AFE_PORT_ID_TERTIARY_TDM_TX_6, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_TX_6, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_TX_6},
- { AFE_PORT_ID_TERTIARY_TDM_RX_7, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_RX_7, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_RX_7},
- { AFE_PORT_ID_TERTIARY_TDM_TX_7, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_TERTIARY_TDM_TX_7, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_TERT_TDM_TX_7},
- { AFE_PORT_ID_QUATERNARY_TDM_RX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_RX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_RX_0},
- { AFE_PORT_ID_QUATERNARY_TDM_TX, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_TX, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_TX_0},
- { AFE_PORT_ID_QUATERNARY_TDM_RX_1, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_RX_1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_RX_1},
- { AFE_PORT_ID_QUATERNARY_TDM_TX_1, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_TX_1, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_TX_1},
- { AFE_PORT_ID_QUATERNARY_TDM_RX_2, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_RX_2, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_RX_2},
- { AFE_PORT_ID_QUATERNARY_TDM_TX_2, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_TX_2, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_TX_2},
- { AFE_PORT_ID_QUATERNARY_TDM_RX_3, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_RX_3, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_RX_3},
- { AFE_PORT_ID_QUATERNARY_TDM_TX_3, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_TX_3, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_TX_3},
- { AFE_PORT_ID_QUATERNARY_TDM_RX_4, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_RX_4, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_RX_4},
- { AFE_PORT_ID_QUATERNARY_TDM_TX_4, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_TX_4, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_TX_4},
- { AFE_PORT_ID_QUATERNARY_TDM_RX_5, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_RX_5, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_RX_5},
- { AFE_PORT_ID_QUATERNARY_TDM_TX_5, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_TX_5, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_TX_5},
- { AFE_PORT_ID_QUATERNARY_TDM_RX_6, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_RX_6, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_RX_6},
- { AFE_PORT_ID_QUATERNARY_TDM_TX_6, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_TX_6, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_TX_6},
- { AFE_PORT_ID_QUATERNARY_TDM_RX_7, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_RX_7, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_RX_7},
- { AFE_PORT_ID_QUATERNARY_TDM_TX_7, 0, 0, 0, 0, 0, 0, 0,
+ { AFE_PORT_ID_QUATERNARY_TDM_TX_7, 0, 0, 0, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_TDM_TX_7},
- { INT_BT_A2DP_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_A2DP_RX},
- { SLIMBUS_7_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_RX},
- { SLIMBUS_7_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_TX},
- { SLIMBUS_8_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_RX},
- { SLIMBUS_8_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_TX},
- { AFE_PORT_ID_USB_RX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_USB_AUDIO_RX},
- { AFE_PORT_ID_USB_TX, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_USB_AUDIO_TX},
+ { INT_BT_A2DP_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_A2DP_RX},
+ { SLIMBUS_7_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_RX},
+ { SLIMBUS_7_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_TX},
+ { SLIMBUS_8_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_RX},
+ { SLIMBUS_8_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_TX},
+ { AFE_PORT_ID_USB_RX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_USB_AUDIO_RX},
+ { AFE_PORT_ID_USB_TX, 0, 0, 0, 0, 0, 0, 0, 0, LPASS_BE_USB_AUDIO_TX},
};
/* Track ASM playback & capture sessions of DAI */
@@ -828,7 +832,15 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode,
(msm_bedais[i].active) &&
(test_bit(fe_id, &msm_bedais[i].fe_sessions))) {
int app_type, app_type_idx, copp_idx, acdb_dev_id;
- channels = msm_bedais[i].channel;
+
+ /*
+ * check if ADM needs to be configured with different
+ * channel mapping than backend
+ */
+ if (!msm_bedais[i].adm_override_ch)
+ channels = msm_bedais[i].channel;
+ else
+ channels = msm_bedais[i].adm_override_ch;
bit_width = msm_routing_get_bit_width(
msm_bedais[i].format);
@@ -976,7 +988,14 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode,
(msm_bedais[i].active) &&
(test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
int app_type, app_type_idx, copp_idx, acdb_dev_id;
- channels = msm_bedais[i].channel;
+ /*
+ * check if ADM needs to be configured with different
+ * channel mapping than backend
+ */
+ if (!msm_bedais[i].adm_override_ch)
+ channels = msm_bedais[i].channel;
+ else
+ channels = msm_bedais[i].adm_override_ch;
msm_bedais[i].compr_passthr_mode =
LEGACY_PCM;
@@ -1188,7 +1207,14 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
if (msm_bedais[reg].active && fdai->strm_id !=
INVALID_SESSION) {
int app_type, app_type_idx, copp_idx, acdb_dev_id;
- channels = msm_bedais[reg].channel;
+ /*
+ * check if ADM needs to be configured with different
+ * channel mapping than backend
+ */
+ if (!msm_bedais[reg].adm_override_ch)
+ channels = msm_bedais[reg].channel;
+ else
+ channels = msm_bedais[reg].adm_override_ch;
if (session_type == SESSION_TYPE_TX &&
fdai->be_srate &&
(fdai->be_srate != msm_bedais[reg].sample_rate)) {
@@ -1855,6 +1881,68 @@ static int msm_routing_lsm_func_put(struct snd_kcontrol *kcontrol,
return afe_port_set_mad_type(port_id, mad_type);
}
+static const char *const adm_override_chs_text[] = {"Zero", "One", "Two"};
+
+static SOC_ENUM_SINGLE_EXT_DECL(slim_7_rx_adm_override_chs,
+ adm_override_chs_text);
+
+static int msm_routing_adm_get_backend_idx(struct snd_kcontrol *kcontrol)
+{
+ int backend_id;
+
+ if (strnstr(kcontrol->id.name, "SLIM7_RX", sizeof("SLIM7_RX"))) {
+ backend_id = MSM_BACKEND_DAI_SLIMBUS_7_RX;
+ } else {
+ pr_err("%s: unsupported backend id: %s",
+ __func__, kcontrol->id.name);
+ return -EINVAL;
+ }
+
+ return backend_id;
+}
+static int msm_routing_adm_channel_config_get(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int backend_id = msm_routing_adm_get_backend_idx(kcontrol);
+
+ if (backend_id >= 0) {
+ mutex_lock(&routing_lock);
+ ucontrol->value.integer.value[0] =
+ msm_bedais[backend_id].adm_override_ch;
+ pr_debug("%s: adm channel count %ld for BE:%d\n", __func__,
+ ucontrol->value.integer.value[0], backend_id);
+ mutex_unlock(&routing_lock);
+ }
+
+ return 0;
+}
+
+static int msm_routing_adm_channel_config_put(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int backend_id = msm_routing_adm_get_backend_idx(kcontrol);
+
+ if (backend_id >= 0) {
+ mutex_lock(&routing_lock);
+ msm_bedais[backend_id].adm_override_ch =
+ ucontrol->value.integer.value[0];
+ pr_debug("%s:updating BE :%d adm channels: %d\n",
+ __func__, backend_id,
+ msm_bedais[backend_id].adm_override_ch);
+ mutex_unlock(&routing_lock);
+ }
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new adm_channel_config_controls[] = {
+ SOC_ENUM_EXT("SLIM7_RX ADM Channels", slim_7_rx_adm_override_chs,
+ msm_routing_adm_channel_config_get,
+ msm_routing_adm_channel_config_put),
+};
+
static int msm_routing_slim_0_rx_aanc_mux_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -9641,7 +9729,14 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream)
app_type_cfg[app_type_idx].bit_width;
} else
sample_rate = bedai->sample_rate;
- channels = bedai->channel;
+ /*
+ * check if ADM needs to be configured with different
+ * channel mapping than backend
+ */
+ if (!bedai->adm_override_ch)
+ channels = bedai->channel;
+ else
+ channels = bedai->adm_override_ch;
acdb_dev_id = fe_dai_app_type_cfg[i].acdb_dev_id;
topology = msm_routing_get_adm_topology(path_type, i);
copp_idx = adm_open(bedai->port_id, path_type,
@@ -9919,7 +10014,9 @@ static int msm_routing_probe(struct snd_soc_platform *platform)
msm_dts_eagle_add_controls(platform);
snd_soc_add_platform_controls(platform, msm_source_tracking_controls,
- ARRAY_SIZE(msm_source_tracking_controls));
+ ARRAY_SIZE(msm_source_tracking_controls));
+ snd_soc_add_platform_controls(platform, adm_channel_config_controls,
+ ARRAY_SIZE(adm_channel_config_controls));
return 0;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 992d0d48e999..f422fd7d3e85 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -360,6 +360,7 @@ struct msm_pcm_routing_bdai_data {
unsigned int sample_rate;
unsigned int channel;
unsigned int format;
+ unsigned int adm_override_ch;
u32 compr_passthr_mode;
char *name;
};
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index b76cb7f4b210..16c7ef4c0bf5 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -292,11 +292,13 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
this_afe.tx_cb(data->opcode, data->token,
data->payload,
this_afe.tx_private_data);
+ this_afe.tx_cb = NULL;
}
if (this_afe.rx_cb) {
this_afe.rx_cb(data->opcode, data->token,
data->payload,
this_afe.rx_private_data);
+ this_afe.rx_cb = NULL;
}
return 0;
@@ -2632,8 +2634,113 @@ exit:
return ret;
}
-int afe_port_start(u16 port_id, union afe_port_config *afe_config,
- u32 rate) /* This function is no blocking */
+static int q6afe_send_enc_config(u16 port_id,
+ union afe_enc_config_data *cfg, u32 format,
+ union afe_port_config afe_config, u16 afe_in_channels)
+{
+ struct afe_audioif_config_command config;
+ int index;
+ int ret;
+ int payload_size = sizeof(config) - sizeof(struct apr_hdr) -
+ sizeof(config.param) - sizeof(config.port);
+
+ pr_debug("%s:update DSP for enc format = %d\n", __func__, format);
+ if (format != ASM_MEDIA_FMT_SBC && format != ASM_MEDIA_FMT_AAC_V2 &&
+ format != ASM_MEDIA_FMT_APTX && format != ASM_MEDIA_FMT_APTX_HD) {
+ pr_err("%s:Unsuppported format Ignore AFE config\n", __func__);
+ return 0;
+ }
+ memset(&config, 0, sizeof(config));
+ index = q6audio_get_port_index(port_id);
+ config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ config.hdr.pkt_size = sizeof(config);
+ config.hdr.src_port = 0;
+ config.hdr.dest_port = 0;
+ config.hdr.token = index;
+
+ config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
+ config.param.port_id = q6audio_get_port_id(port_id);
+ config.param.payload_size = payload_size + sizeof(config.port.enc_fmt);
+ config.param.payload_address_lsw = 0x00;
+ config.param.payload_address_msw = 0x00;
+ config.param.mem_map_handle = 0x00;
+ config.pdata.module_id = AFE_MODULE_ID_ENCODER;
+ config.pdata.param_id = AFE_ENCODER_PARAM_ID_ENC_FMT_ID;
+ config.pdata.param_size = sizeof(config.port.enc_fmt);
+ config.port.enc_fmt.fmt_id = format;
+ pr_debug("%s:sending AFE_ENCODER_PARAM_ID_ENC_FMT_ID payload: %d\n",
+ __func__, config.param.payload_size);
+ ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+ if (ret) {
+ pr_err("%s:unable to send AFE_ENCODER_PARAM_ID_ENC_FMT_ID",
+ __func__);
+ goto exit;
+ }
+
+ config.param.payload_size = payload_size
+ + sizeof(config.port.enc_blk_param);
+ pr_debug("%s:send AFE_ENCODER_PARAM_ID_ENC_CFG_BLK to DSP payload:%d\n",
+ __func__, config.param.payload_size);
+ config.pdata.param_id = AFE_ENCODER_PARAM_ID_ENC_CFG_BLK;
+ config.pdata.param_size = sizeof(config.port.enc_blk_param);
+ config.port.enc_blk_param.enc_cfg_blk_size =
+ sizeof(config.port.enc_blk_param.enc_blk_config);
+ config.port.enc_blk_param.enc_blk_config = *cfg;
+ ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+ if (ret) {
+ pr_err("%s: AFE_ENCODER_PARAM_ID_ENC_CFG_BLK for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto exit;
+ }
+
+ config.param.payload_size =
+ payload_size + sizeof(config.port.enc_pkt_id_param);
+ pr_debug("%s:sending AFE_ENCODER_PARAM_ID_PACKETIZER to DSP payload = %d",
+ __func__, config.param.payload_size);
+ config.pdata.param_id = AFE_ENCODER_PARAM_ID_PACKETIZER_ID;
+ config.pdata.param_size = sizeof(config.port.enc_pkt_id_param);
+ config.port.enc_pkt_id_param.enc_packetizer_id =
+ AFE_MODULE_ID_PACKETIZER_COP;
+ ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+ if (ret) {
+ pr_err("%s: AFE_ENCODER_PARAM_ID_PACKETIZER for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto exit;
+ }
+
+ config.param.payload_size =
+ payload_size + sizeof(config.port.media_type);
+ config.pdata.param_size = sizeof(config.port.media_type);
+
+ pr_debug("%s:Sending AFE_API_VERSION_PORT_MEDIA_TYPE to DSP", __func__);
+ config.pdata.module_id = AFE_MODULE_PORT;
+ config.pdata.param_id = AFE_PARAM_ID_PORT_MEDIA_TYPE;
+ config.port.media_type.minor_version = AFE_API_VERSION_PORT_MEDIA_TYPE;
+ config.port.media_type.sample_rate = afe_config.slim_sch.sample_rate;
+ config.port.media_type.bit_width = afe_config.slim_sch.bit_width;
+ if (afe_in_channels != 0)
+ config.port.media_type.num_channels = afe_in_channels;
+ else
+ config.port.media_type.num_channels =
+ afe_config.slim_sch.num_channels;
+ config.port.media_type.data_format = AFE_PORT_DATA_FORMAT_PCM;
+ config.port.media_type.reserved = 0;
+
+ ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+ if (ret) {
+ pr_err("%s: AFE_API_VERSION_PORT_MEDIA_TYPE for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto exit;
+ }
+
+exit:
+ return ret;
+}
+
+static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
+ u32 rate, u16 afe_in_channels,
+ union afe_enc_config_data *cfg, u32 enc_format)
{
struct afe_audioif_config_command config;
int ret = 0;
@@ -2850,7 +2957,11 @@ int afe_port_start(u16 port_id, union afe_port_config *afe_config,
config.pdata.param_size = sizeof(config.port);
config.port = *afe_config;
-
+ if ((enc_format != ASM_MEDIA_FMT_NONE) &&
+ (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
+ config.port.slim_sch.data_format =
+ AFE_SB_DATA_FORMAT_GENERIC_COMPRESSED;
+ }
ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
if (ret) {
pr_err("%s: AFE enable for port 0x%x failed %d\n",
@@ -2858,6 +2969,19 @@ int afe_port_start(u16 port_id, union afe_port_config *afe_config,
goto fail_cmd;
}
+ if ((enc_format != ASM_MEDIA_FMT_NONE) &&
+ (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
+ pr_debug("%s: Found AFE encoder support for SLIMBUS enc_format = %d\n",
+ __func__, enc_format);
+ ret = q6afe_send_enc_config(port_id, cfg, enc_format,
+ *afe_config, afe_in_channels);
+ if (ret) {
+ pr_err("%s: AFE encoder config for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto fail_cmd;
+ }
+ }
+
port_index = afe_get_port_index(port_id);
if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) {
this_afe.afe_sample_rates[port_index] = rate;
@@ -2890,6 +3014,47 @@ fail_cmd:
return ret;
}
+/**
+ * afe_port_start - to configure AFE session with
+ * specified port configuration
+ *
+ * @port_id: AFE port id number
+ * @afe_config: port configutation
+ * @rate: sampling rate of port
+ *
+ * Returns 0 on success or error value on port start failure.
+ */
+int afe_port_start(u16 port_id, union afe_port_config *afe_config,
+ u32 rate)
+{
+ return __afe_port_start(port_id, afe_config, rate,
+ 0, NULL, ASM_MEDIA_FMT_NONE);
+}
+EXPORT_SYMBOL(afe_port_start);
+
+/**
+ * afe_port_start_v2 - to configure AFE session with
+ * specified port configuration and encoder params
+ *
+ * @port_id: AFE port id number
+ * @afe_config: port configutation
+ * @rate: sampling rate of port
+ * @cfg: AFE encoder configuration information to setup encoder
+ * @afe_in_channels: AFE input channel configuration, this needs
+ * update only if input channel is differ from AFE output
+ *
+ * Returns 0 on success or error value on port start failure.
+ */
+int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config,
+ u32 rate, u16 afe_in_channels,
+ struct afe_enc_config *enc_cfg)
+{
+ return __afe_port_start(port_id, afe_config, rate,
+ afe_in_channels, &enc_cfg->data,
+ enc_cfg->format);
+}
+EXPORT_SYMBOL(afe_port_start_v2);
+
int afe_get_port_index(u16 port_id)
{
switch (port_id) {