summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,mmcc.txt1
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt71
-rw-r--r--Documentation/devicetree/bindings/power/supply/qcom/smb1351-charger.txt2
-rw-r--r--Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt3
-rw-r--r--arch/arm/boot/dts/qcom/Makefile6
-rw-r--r--arch/arm/boot/dts/qcom/msm-smb138x.dtsi28
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-v2-qrd-skuk-hdk.dts6
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-vidc.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-camera-sensor-cdp.dtsi370
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-camera-sensor-mtp.dtsi370
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-camera.dtsi865
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-cdp.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-headset-jacktype-no-cdp.dts26
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-headset-jacktype-no-rcm.dts26
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mdss.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mtp.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-pm660a-headset-jacktype-no-cdp.dts26
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-pm660a-headset-jacktype-no-rcm.dts26
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-qrd.dtsi22
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-regulator.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/sdm630.dtsi16
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-audio.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-camera.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mdss.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mtp.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-qrd.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-regulator.dtsi60
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-vidc.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/sdm660.dtsi2
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig2
-rw-r--r--arch/arm64/configs/msmcortex_defconfig2
-rw-r--r--certs/Makefile4
-rw-r--r--certs/verity.x509.pem24
-rw-r--r--drivers/bluetooth/btfm_slim.c2
-rw-r--r--drivers/bluetooth/btfm_slim.h4
-rw-r--r--drivers/bluetooth/btfm_slim_codec.c18
-rw-r--r--drivers/bluetooth/btfm_slim_wcn3990.c4
-rw-r--r--drivers/clk/msm/clock-generic.c14
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.c1
-rw-r--r--drivers/clk/qcom/clk-smd-rpm.c4
-rw-r--r--drivers/clk/qcom/gcc-sdm660.c61
-rw-r--r--drivers/clk/qcom/mmcc-sdm660.c16
-rw-r--r--drivers/gpu/drm/msm/Makefile1
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_gpu.c23
-rw-r--r--drivers/gpu/drm/msm/adreno/a4xx_gpu.c22
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c22
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c40
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h1
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c39
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h2
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c32
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h35
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c73
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h26
-rw-r--r--drivers/gpu/drm/msm/msm_gem_vma.c213
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c18
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h4
-rw-r--r--drivers/gpu/drm/msm/msm_mmu.h2
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.c30
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.h3
-rw-r--r--drivers/gpu/msm/adreno_dispatch.c6
-rw-r--r--drivers/gpu/msm/kgsl.c5
-rw-r--r--drivers/input/touchscreen/Kconfig11
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/msg21xx_ts.c2260
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_base.h1
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c14
-rw-r--r--drivers/mmc/core/core.c12
-rw-r--r--drivers/mmc/host/cmdq_hci.c17
-rw-r--r--drivers/mmc/host/sdhci-msm.c9
-rw-r--r--drivers/net/ppp/ppp_generic.c2
-rw-r--r--drivers/net/wireless/ath/wil6210/pcie_bus.c30
-rw-r--r--drivers/pci/host/pci-msm.c14
-rw-r--r--drivers/phy/phy-qcom-ufs.c8
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_client.c42
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_i.h3
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c8
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c58
-rw-r--r--drivers/power/supply/qcom/battery.c48
-rw-r--r--drivers/power/supply/qcom/qpnp-smb2.c16
-rw-r--r--drivers/power/supply/qcom/smb-lib.c244
-rw-r--r--drivers/power/supply/qcom/smb-lib.h8
-rw-r--r--drivers/power/supply/qcom/smb-reg.h3
-rw-r--r--drivers/power/supply/qcom/smb1351-charger.c9
-rw-r--r--drivers/power/supply/qcom/smb138x-charger.c55
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c179
-rw-r--r--drivers/scsi/ufs/ufs-qcom.h1
-rw-r--r--drivers/soc/qcom/qdsp6v2/audio_notifier.c11
-rw-r--r--drivers/soc/qcom/rpm_rail_stats.c4
-rw-r--r--drivers/usb/gadget/function/u_ether.c2
-rw-r--r--drivers/usb/pd/policy_engine.c14
-rw-r--r--drivers/usb/phy/phy-msm-qusb.c44
-rw-r--r--drivers/video/fbdev/msm/mdss.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c7
-rw-r--r--drivers/video/fbdev/msm/mdss_smmu.c14
-rw-r--r--include/dt-bindings/clock/qcom,gcc-sdm660.h2
-rw-r--r--include/linux/compaction.h16
-rw-r--r--include/linux/mmzone.h6
-rw-r--r--include/linux/power_supply.h7
-rw-r--r--include/linux/vm_event_item.h1
-rw-r--r--include/trace/events/compaction.h55
-rw-r--r--mm/compaction.c222
-rw-r--r--mm/memory_hotplug.c15
-rw-r--r--mm/page_alloc.c3
-rw-r--r--mm/vmpressure.c10
-rw-r--r--mm/vmscan.c19
-rw-r--r--mm/vmstat.c1
-rw-r--r--net/socket.c4
-rw-r--r--sound/soc/msm/Kconfig14
-rw-r--r--sound/soc/msm/msm8998.c31
-rw-r--r--sound/soc/msm/qdsp6v2/Makefile1
-rw-r--r--sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c1092
-rw-r--r--sound/soc/msm/qdsp6v2/q6afe.c32
116 files changed, 3523 insertions, 3873 deletions
diff --git a/Documentation/devicetree/bindings/clock/qcom,mmcc.txt b/Documentation/devicetree/bindings/clock/qcom,mmcc.txt
index 4b1057288b2f..f7b1bfd257fd 100644
--- a/Documentation/devicetree/bindings/clock/qcom,mmcc.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,mmcc.txt
@@ -11,6 +11,7 @@ Required properties :
"qcom,mmcc-msm8974"
"qcom,mmcc-msm8996"
"qcom,mmcc-sdm660"
+ "qcom,mmcc-sdm630"
- reg : shall contain base register location and length
- #clock-cells : shall contain 1
diff --git a/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt
deleted file mode 100644
index 7315aef62493..000000000000
--- a/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt
+++ /dev/null
@@ -1,71 +0,0 @@
-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.
- - mstar,num-max-touches: It defines the maximum number of touch supported by the controller.
- - mstar,hard-reset-delay-ms : hard reset delay in ms
- - mstar,post-hard-reset-delay-ms : post hard reset delay in ms
-
-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.
- - mstar,ic-type : It defines the ic-type of the controller. Values are as folows:
- 1 -> msg2133.
- 2 -> msg21xxA.
- 3 -> msg26xxM.
-
-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>;
- mstar,ic-type = <2>;
- mstar,num_max_touches = <2>;
- mstar,hard-reset-delay-ms = <100>;
- mstar,post-hard-reset-delay-ms = <100>;
- };
- };
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/smb1351-charger.txt b/Documentation/devicetree/bindings/power/supply/qcom/smb1351-charger.txt
index ab0ac32e444e..c200f9423384 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/smb1351-charger.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/smb1351-charger.txt
@@ -69,6 +69,8 @@ Optional Properties:
via pin in a parallel-charger configuration.
0 - Active low and 1 - Active high.
If not specified the default value is active-low.
+- qcom,parallel-external-current-sense If present specifies external rsense is
+ used for charge current sensing.
Example for standalone charger:
diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
index a25961c6e7de..8b99dbce871b 100644
--- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
+++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
@@ -141,6 +141,9 @@ enabled and functional in the driver:
- qcom,pm-qos-default-cpu: PM QoS voting is based on the cpu associated with each IO request by the block layer.
This defined the default cpu used for PM QoS voting in case a specific cpu value is not available.
+- qcom,vddp-ref-clk-supply : reference clock to ufs device. Controlled by the host driver.
+- qcom,vddp-ref-clk-max-microamp : specifies max. load that can be drawn for
+ ref-clk supply.
Example:
ufshc@0xfc598000 {
...
diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
index d572568eb94e..c6cff2e95bb9 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -205,7 +205,11 @@ dtb-$(CONFIG_ARCH_SDM630) += sdm630-rumi.dtb \
sda630-rcm.dtb \
sda630-pm660a-mtp.dtb \
sda630-pm660a-cdp.dtb \
- sda630-pm660a-rcm.dtb
+ sda630-pm660a-rcm.dtb \
+ sdm630-headset-jacktype-no-cdp.dtb \
+ sdm630-headset-jacktype-no-rcm.dtb \
+ sdm630-pm660a-headset-jacktype-no-cdp.dtb \
+ sdm630-pm660a-headset-jacktype-no-rcm.dtb
ifeq ($(CONFIG_ARM64),y)
always := $(dtb-y)
diff --git a/arch/arm/boot/dts/qcom/msm-smb138x.dtsi b/arch/arm/boot/dts/qcom/msm-smb138x.dtsi
index 8edc1fc61830..ea4f05069aab 100644
--- a/arch/arm/boot/dts/qcom/msm-smb138x.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-smb138x.dtsi
@@ -95,18 +95,22 @@
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&smb138x>;
- io-channels = <&smb138x_tadc 2>,
- <&smb138x_tadc 3>,
- <&smb138x_tadc 14>,
- <&smb138x_tadc 15>,
- <&smb138x_tadc 16>,
- <&smb138x_tadc 17>;
- io-channel-names = "charger_temp",
- "batt_i",
- "connector_temp_thr1",
- "connector_temp_thr2",
- "connector_temp_thr3",
- "charger_temp_max";
+ io-channels =
+ <&smb138x_tadc 1>,
+ <&smb138x_tadc 2>,
+ <&smb138x_tadc 3>,
+ <&smb138x_tadc 14>,
+ <&smb138x_tadc 15>,
+ <&smb138x_tadc 16>,
+ <&smb138x_tadc 17>;
+ io-channel-names =
+ "connector_temp",
+ "charger_temp",
+ "batt_i",
+ "connector_temp_thr1",
+ "connector_temp_thr2",
+ "connector_temp_thr3",
+ "charger_temp_max";
qcom,chgr@1000 {
reg = <0x1000 0x100>;
diff --git a/arch/arm/boot/dts/qcom/msm8998-v2-qrd-skuk-hdk.dts b/arch/arm/boot/dts/qcom/msm8998-v2-qrd-skuk-hdk.dts
index ace7fc169703..0e17ce31d52f 100644
--- a/arch/arm/boot/dts/qcom/msm8998-v2-qrd-skuk-hdk.dts
+++ b/arch/arm/boot/dts/qcom/msm8998-v2-qrd-skuk-hdk.dts
@@ -23,6 +23,12 @@
qcom,board-id = <0x06000b 0x10>;
};
+&soc {
+ sound-tavil {
+ qcom,msm-mbhc-hphl-swh = <0>;
+ };
+};
+
&pmx_mdss {
mdss_dsi_active: mdss_dsi_active {
mux {
diff --git a/arch/arm/boot/dts/qcom/msm8998-vidc.dtsi b/arch/arm/boot/dts/qcom/msm8998-vidc.dtsi
index 3e7cacac9d43..05a8816677ed 100644
--- a/arch/arm/boot/dts/qcom/msm8998-vidc.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-vidc.dtsi
@@ -117,7 +117,7 @@
qcom,bus-master = <MSM_BUS_MASTER_VIDEO_P0>;
qcom,bus-slave = <MSM_BUS_SLAVE_EBI_CH0>;
qcom,bus-governor = "msm-vidc-ddr";
- qcom,bus-range-kbps = <1000 3388000>;
+ qcom,bus-range-kbps = <1000 4946000>;
};
venus_bus_vmem {
diff --git a/arch/arm/boot/dts/qcom/sdm630-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/qcom/sdm630-camera-sensor-cdp.dtsi
new file mode 100644
index 000000000000..94158834eee6
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdm630-camera-sensor-cdp.dtsi
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+&soc {
+ led_flash0: qcom,camera-flash@0 {
+ cell-index = <0>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-source = <&pm660l_flash0 &pm660l_flash1>;
+ qcom,torch-source = <&pm660l_torch0 &pm660l_torch1>;
+ qcom,switch-source = <&pm660l_switch0>;
+ status = "ok";
+ };
+
+ led_flash1: qcom,camera-flash@1 {
+ cell-index = <1>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-source = <&pm660l_flash2>;
+ qcom,torch-source = <&pm660l_torch2>;
+ qcom,switch-source = <&pm660l_switch1>;
+ status = "ok";
+ };
+};
+
+&cci {
+ actuator0: qcom,actuator@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ cam_vaf-supply = <&pm660l_l8>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2800000>;
+ qcom,cam-vreg-max-voltage = <3400000>;
+ qcom,cam-vreg-op-mode = <100000>;
+ };
+
+ actuator1: qcom,actuator@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <1>;
+ cam_vaf-supply = <&pm660l_l8>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2800000>;
+ qcom,cam-vreg-max-voltage = <3400000>;
+ qcom,cam-vreg-op-mode = <100000>;
+ };
+
+ actuator2: qcom,actuator@2 {
+ cell-index = <2>;
+ reg = <0x2>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <1>;
+ cam_vaf-supply = <&pm660l_l8>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2800000>;
+ qcom,cam-vreg-max-voltage = <3400000>;
+ qcom,cam-vreg-op-mode = <100000>;
+ };
+
+ ois0: qcom,ois@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,ois";
+ qcom,cci-master = <0>;
+ gpios = <&tlmm 50 0>;
+ qcom,gpio-vaf = <0>;
+ qcom,gpio-req-tbl-num = <0>;
+ qcom,gpio-req-tbl-flags = <0>;
+ qcom,gpio-req-tbl-label = "CAM_VAF";
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_actuator_vaf_active>;
+ pinctrl-1 = <&cam_actuator_vaf_suspend>;
+ status = "disabled";
+ };
+
+ eeprom0: qcom,eeprom@0 {
+ cell-index = <0>;
+ reg = <0>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pm660_l11>;
+ cam_vana-supply = <&pm660l_bob>;
+ cam_vdig-supply = <&pm660_s5>;
+ cam_vaf-supply = <&pm660l_l8>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1780000 3300000 1350000 2800000>;
+ qcom,cam-vreg-max-voltage = <1950000 3600000 1350000 3400000>;
+ qcom,cam-vreg-op-mode = <105000 80000 105000 100000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear_suspend>;
+ gpios = <&tlmm 32 0>,
+ <&tlmm 46 0>,
+ <&pm660l_gpios 4 0>,
+ <&tlmm 51 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-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_VDIG",
+ "CAM_VANA";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_mmss MCLK0_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_MCLK0_CLK>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ eeprom1: qcom,eeprom@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pm660_l11>;
+ cam_vana-supply = <&pm660l_bob>;
+ cam_vdig-supply = <&pm660_s5>;
+ cam_vaf-supply = <&pm660l_l8>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1780000 3300000 1350000 2800000>;
+ qcom,cam-vreg-max-voltage = <1950000 3600000 1350000 3400000>;
+ qcom,cam-vreg-op-mode = <105000 80000 105000 100000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 34 0>,
+ <&tlmm 48 0>,
+ <&pm660l_gpios 3 0>,
+ <&tlmm 51 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-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET",
+ "CAM_VDIG",
+ "CAM_VANA";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_mmss MCLK2_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_MCLK2_CLK>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ eeprom2: qcom,eeprom@2 {
+ cell-index = <2>;
+ reg = <0x2>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pm660_l11>;
+ cam_vana-supply = <&pm660l_bob>;
+ cam_vdig-supply = <&pm660_s5>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1780000 3300000 1350000 2800000>;
+ qcom,cam-vreg-max-voltage = <1950000 3600000 1350000 3400000>;
+ qcom,cam-vreg-op-mode = <105000 80000 105000 100000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_front_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_front_suspend>;
+ gpios = <&tlmm 33 0>,
+ <&tlmm 47 0>,
+ <&pm660_gpios 3 0>,
+ <&tlmm 44 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-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_VDIG",
+ "CAM_VANA";
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_mmss MCLK1_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_MCLK1_CLK>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@0 {
+ cell-index = <0>;
+ compatible = "qcom,camera";
+ reg = <0x0>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <270>;
+ qcom,led-flash-src = <&led_flash0>;
+ qcom,actuator-src = <&actuator0>;
+ qcom,ois-src = <&ois0>;
+ qcom,eeprom-src = <&eeprom0>;
+ cam_vio-supply = <&pm660_l11>;
+ cam_vana-supply = <&pm660l_bob>;
+ cam_vdig-supply = <&pm660_s5>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>;
+ qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>;
+ qcom,cam-vreg-op-mode = <105000 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear_suspend>;
+ gpios = <&tlmm 32 0>,
+ <&tlmm 46 0>,
+ <&pm660l_gpios 4 0>,
+ <&tlmm 51 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-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_VDIG",
+ "CAM_VANA";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_mmss MCLK0_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_MCLK0_CLK>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@1 {
+ cell-index = <1>;
+ compatible = "qcom,camera";
+ reg = <0x1>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <2>;
+ qcom,mount-angle = <90>;
+ qcom,actuator-src = <&actuator1>;
+ qcom,eeprom-src = <&eeprom1>;
+ cam_vio-supply = <&pm660_l11>;
+ cam_vana-supply = <&pm660l_bob>;
+ cam_vdig-supply = <&pm660_s5>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>;
+ qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>;
+ qcom,cam-vreg-op-mode = <105000 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 34 0>,
+ <&tlmm 48 0>,
+ <&pm660l_gpios 3 0>,
+ <&tlmm 51 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-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET",
+ "CAM_VDIG",
+ "CAM_VANA";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_mmss MCLK2_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_MCLK2_CLK>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@2 {
+ cell-index = <2>;
+ compatible = "qcom,camera";
+ reg = <0x02>;
+ qcom,csiphy-sd-index = <2>;
+ qcom,csid-sd-index = <2>;
+ qcom,mount-angle = <90>;
+ qcom,actuator-src = <&actuator2>;
+ qcom,eeprom-src = <&eeprom2>;
+ cam_vio-supply = <&pm660_l11>;
+ cam_vana-supply = <&pm660l_bob>;
+ cam_vdig-supply = <&pm660_s5>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>;
+ qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>;
+ qcom,cam-vreg-op-mode = <105000 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_front_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_front_suspend>;
+ gpios = <&tlmm 33 0>,
+ <&tlmm 47 0>,
+ <&pm660l_gpios 3 0>,
+ <&tlmm 51 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-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_VDIG",
+ "CAM_VANA";
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_mmss MCLK1_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_MCLK1_CLK>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+};
+
+&pm660l_gpios {
+ gpio@c300 { /* GPIO4 -CAMERA SENSOR 0 VDIG*/
+ qcom,mode = <1>; /* Output */
+ qcom,pull = <5>; /* No Pull */
+ qcom,vin-sel = <0>; /* VIN1 GPIO_LV */
+ qcom,src-sel = <0>; /* GPIO */
+ qcom,invert = <0>; /* Invert */
+ qcom,master-en = <1>; /* Enable GPIO */
+ status = "ok";
+ };
+
+ gpio@c200 { /* GPIO3 -CAMERA SENSOR 2 VDIG*/
+ qcom,mode = <1>; /* Output */
+ qcom,pull = <5>; /* No Pull */
+ qcom,vin-sel = <0>; /* VIN1 GPIO_LV */
+ qcom,src-sel = <0>; /* GPIO */
+ qcom,invert = <0>; /* Invert */
+ qcom,master-en = <1>; /* Enable GPIO */
+ status = "ok";
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/qcom/sdm630-camera-sensor-mtp.dtsi
new file mode 100644
index 000000000000..94158834eee6
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdm630-camera-sensor-mtp.dtsi
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+&soc {
+ led_flash0: qcom,camera-flash@0 {
+ cell-index = <0>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-source = <&pm660l_flash0 &pm660l_flash1>;
+ qcom,torch-source = <&pm660l_torch0 &pm660l_torch1>;
+ qcom,switch-source = <&pm660l_switch0>;
+ status = "ok";
+ };
+
+ led_flash1: qcom,camera-flash@1 {
+ cell-index = <1>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-source = <&pm660l_flash2>;
+ qcom,torch-source = <&pm660l_torch2>;
+ qcom,switch-source = <&pm660l_switch1>;
+ status = "ok";
+ };
+};
+
+&cci {
+ actuator0: qcom,actuator@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ cam_vaf-supply = <&pm660l_l8>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2800000>;
+ qcom,cam-vreg-max-voltage = <3400000>;
+ qcom,cam-vreg-op-mode = <100000>;
+ };
+
+ actuator1: qcom,actuator@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <1>;
+ cam_vaf-supply = <&pm660l_l8>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2800000>;
+ qcom,cam-vreg-max-voltage = <3400000>;
+ qcom,cam-vreg-op-mode = <100000>;
+ };
+
+ actuator2: qcom,actuator@2 {
+ cell-index = <2>;
+ reg = <0x2>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <1>;
+ cam_vaf-supply = <&pm660l_l8>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2800000>;
+ qcom,cam-vreg-max-voltage = <3400000>;
+ qcom,cam-vreg-op-mode = <100000>;
+ };
+
+ ois0: qcom,ois@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,ois";
+ qcom,cci-master = <0>;
+ gpios = <&tlmm 50 0>;
+ qcom,gpio-vaf = <0>;
+ qcom,gpio-req-tbl-num = <0>;
+ qcom,gpio-req-tbl-flags = <0>;
+ qcom,gpio-req-tbl-label = "CAM_VAF";
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_actuator_vaf_active>;
+ pinctrl-1 = <&cam_actuator_vaf_suspend>;
+ status = "disabled";
+ };
+
+ eeprom0: qcom,eeprom@0 {
+ cell-index = <0>;
+ reg = <0>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pm660_l11>;
+ cam_vana-supply = <&pm660l_bob>;
+ cam_vdig-supply = <&pm660_s5>;
+ cam_vaf-supply = <&pm660l_l8>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1780000 3300000 1350000 2800000>;
+ qcom,cam-vreg-max-voltage = <1950000 3600000 1350000 3400000>;
+ qcom,cam-vreg-op-mode = <105000 80000 105000 100000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear_suspend>;
+ gpios = <&tlmm 32 0>,
+ <&tlmm 46 0>,
+ <&pm660l_gpios 4 0>,
+ <&tlmm 51 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-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_VDIG",
+ "CAM_VANA";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_mmss MCLK0_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_MCLK0_CLK>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ eeprom1: qcom,eeprom@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pm660_l11>;
+ cam_vana-supply = <&pm660l_bob>;
+ cam_vdig-supply = <&pm660_s5>;
+ cam_vaf-supply = <&pm660l_l8>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1780000 3300000 1350000 2800000>;
+ qcom,cam-vreg-max-voltage = <1950000 3600000 1350000 3400000>;
+ qcom,cam-vreg-op-mode = <105000 80000 105000 100000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 34 0>,
+ <&tlmm 48 0>,
+ <&pm660l_gpios 3 0>,
+ <&tlmm 51 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-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET",
+ "CAM_VDIG",
+ "CAM_VANA";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_mmss MCLK2_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_MCLK2_CLK>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ eeprom2: qcom,eeprom@2 {
+ cell-index = <2>;
+ reg = <0x2>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pm660_l11>;
+ cam_vana-supply = <&pm660l_bob>;
+ cam_vdig-supply = <&pm660_s5>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1780000 3300000 1350000 2800000>;
+ qcom,cam-vreg-max-voltage = <1950000 3600000 1350000 3400000>;
+ qcom,cam-vreg-op-mode = <105000 80000 105000 100000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_front_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_front_suspend>;
+ gpios = <&tlmm 33 0>,
+ <&tlmm 47 0>,
+ <&pm660_gpios 3 0>,
+ <&tlmm 44 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-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_VDIG",
+ "CAM_VANA";
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_mmss MCLK1_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_MCLK1_CLK>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@0 {
+ cell-index = <0>;
+ compatible = "qcom,camera";
+ reg = <0x0>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <270>;
+ qcom,led-flash-src = <&led_flash0>;
+ qcom,actuator-src = <&actuator0>;
+ qcom,ois-src = <&ois0>;
+ qcom,eeprom-src = <&eeprom0>;
+ cam_vio-supply = <&pm660_l11>;
+ cam_vana-supply = <&pm660l_bob>;
+ cam_vdig-supply = <&pm660_s5>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>;
+ qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>;
+ qcom,cam-vreg-op-mode = <105000 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear_suspend>;
+ gpios = <&tlmm 32 0>,
+ <&tlmm 46 0>,
+ <&pm660l_gpios 4 0>,
+ <&tlmm 51 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-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_VDIG",
+ "CAM_VANA";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_mmss MCLK0_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_MCLK0_CLK>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@1 {
+ cell-index = <1>;
+ compatible = "qcom,camera";
+ reg = <0x1>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <2>;
+ qcom,mount-angle = <90>;
+ qcom,actuator-src = <&actuator1>;
+ qcom,eeprom-src = <&eeprom1>;
+ cam_vio-supply = <&pm660_l11>;
+ cam_vana-supply = <&pm660l_bob>;
+ cam_vdig-supply = <&pm660_s5>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>;
+ qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>;
+ qcom,cam-vreg-op-mode = <105000 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 34 0>,
+ <&tlmm 48 0>,
+ <&pm660l_gpios 3 0>,
+ <&tlmm 51 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-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET",
+ "CAM_VDIG",
+ "CAM_VANA";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_mmss MCLK2_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_MCLK2_CLK>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@2 {
+ cell-index = <2>;
+ compatible = "qcom,camera";
+ reg = <0x02>;
+ qcom,csiphy-sd-index = <2>;
+ qcom,csid-sd-index = <2>;
+ qcom,mount-angle = <90>;
+ qcom,actuator-src = <&actuator2>;
+ qcom,eeprom-src = <&eeprom2>;
+ cam_vio-supply = <&pm660_l11>;
+ cam_vana-supply = <&pm660l_bob>;
+ cam_vdig-supply = <&pm660_s5>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>;
+ qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>;
+ qcom,cam-vreg-op-mode = <105000 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_front_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_front_suspend>;
+ gpios = <&tlmm 33 0>,
+ <&tlmm 47 0>,
+ <&pm660l_gpios 3 0>,
+ <&tlmm 51 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-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_VDIG",
+ "CAM_VANA";
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_mmss MCLK1_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_MCLK1_CLK>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+};
+
+&pm660l_gpios {
+ gpio@c300 { /* GPIO4 -CAMERA SENSOR 0 VDIG*/
+ qcom,mode = <1>; /* Output */
+ qcom,pull = <5>; /* No Pull */
+ qcom,vin-sel = <0>; /* VIN1 GPIO_LV */
+ qcom,src-sel = <0>; /* GPIO */
+ qcom,invert = <0>; /* Invert */
+ qcom,master-en = <1>; /* Enable GPIO */
+ status = "ok";
+ };
+
+ gpio@c200 { /* GPIO3 -CAMERA SENSOR 2 VDIG*/
+ qcom,mode = <1>; /* Output */
+ qcom,pull = <5>; /* No Pull */
+ qcom,vin-sel = <0>; /* VIN1 GPIO_LV */
+ qcom,src-sel = <0>; /* GPIO */
+ qcom,invert = <0>; /* Invert */
+ qcom,master-en = <1>; /* Enable GPIO */
+ status = "ok";
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-camera.dtsi b/arch/arm/boot/dts/qcom/sdm630-camera.dtsi
new file mode 100644
index 000000000000..56210dc6892b
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdm630-camera.dtsi
@@ -0,0 +1,865 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+&soc {
+ qcom,msm-cam@ca00000 {
+ compatible = "qcom,msm-cam";
+ reg = <0xca00000 0x4000>;
+ reg-names = "msm-cam";
+ status = "ok";
+ bus-vectors = "suspend", "svs", "nominal", "turbo";
+ qcom,bus-votes = <0 150000000 320000000 320000000>;
+ };
+
+ qcom,csiphy@c824000 {
+ cell-index = <0>;
+ compatible = "qcom,csiphy-v3.5", "qcom,csiphy";
+ reg = <0xc824000 0x1000>,
+ <0xca00120 0x4>;
+ reg-names = "csiphy", "csiphy_clk_mux";
+ interrupts = <0 78 0>;
+ interrupt-names = "csiphy";
+ gdscr-supply = <&gdsc_camss_top>;
+ bimc_smmu-supply = <&gdsc_bimc_smmu>;
+ qcom,cam-vreg-name = "gdscr", "bimc_smmu";
+ clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
+ <&clock_mmss MMSS_MNOC_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>,
+ <&clock_mmss MMSS_CAMSS_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_TOP_AHB_CLK>,
+ <&clock_mmss CSI0_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSI0_CLK>,
+ <&clock_mmss MMSS_CAMSS_CPHY_CSID0_CLK>,
+ <&clock_mmss CSI0PHYTIMER_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSI0PHYTIMER_CLK>,
+ <&clock_mmss MMSS_CAMSS_ISPIF_AHB_CLK>,
+ <&clock_mmss CSIPHY_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSIPHY0_CLK>,
+ <&clock_mmss MMSS_CSIPHY_AHB2CRIF_CLK>;
+ clock-names = "mmssnoc_axi", "mnoc_ahb",
+ "bmic_smmu_ahb", "bmic_smmu_axi",
+ "camss_ahb_clk", "camss_top_ahb_clk",
+ "csi_src_clk", "csi_clk", "cphy_csid_clk",
+ "csiphy_timer_src_clk", "csiphy_timer_clk",
+ "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk",
+ "csiphy_ahb2crif";
+ qcom,clock-rates = <0 0 0 0 0 0 384000000 0 0 269333333 0
+ 0 384000000 0 0>;
+ status = "ok";
+ };
+
+ qcom,csiphy@c825000 {
+ cell-index = <1>;
+ compatible = "qcom,csiphy-v3.5", "qcom,csiphy";
+ reg = <0xc825000 0x1000>,
+ <0xca00124 0x4>;
+ reg-names = "csiphy", "csiphy_clk_mux";
+ interrupts = <0 79 0>;
+ interrupt-names = "csiphy";
+ gdscr-supply = <&gdsc_camss_top>;
+ bimc_smmu-supply = <&gdsc_bimc_smmu>;
+ qcom,cam-vreg-name = "gdscr", "bimc_smmu";
+ clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
+ <&clock_mmss MMSS_MNOC_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>,
+ <&clock_mmss MMSS_CAMSS_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_TOP_AHB_CLK>,
+ <&clock_mmss CSI1_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSI1_CLK>,
+ <&clock_mmss MMSS_CAMSS_CPHY_CSID1_CLK>,
+ <&clock_mmss CSI1PHYTIMER_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSI1PHYTIMER_CLK>,
+ <&clock_mmss MMSS_CAMSS_ISPIF_AHB_CLK>,
+ <&clock_mmss CSIPHY_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSIPHY1_CLK>,
+ <&clock_mmss MMSS_CSIPHY_AHB2CRIF_CLK>;
+ clock-names = "mmssnoc_axi", "mnoc_ahb",
+ "bmic_smmu_ahb", "bmic_smmu_axi",
+ "camss_ahb_clk", "camss_top_ahb_clk",
+ "csi_src_clk", "csi_clk", "cphy_csid_clk",
+ "csiphy_timer_src_clk", "csiphy_timer_clk",
+ "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk",
+ "csiphy_ahb2crif";
+ qcom,clock-rates = <0 0 0 0 0 0 384000000 0 0 269333333 0
+ 0 384000000 0 0>;
+ status = "ok";
+ };
+
+ qcom,csiphy@c826000 {
+ cell-index = <2>;
+ compatible = "qcom,csiphy-v3.5", "qcom,csiphy";
+ reg = <0xc826000 0x1000>,
+ <0xca00128 0x4>;
+ reg-names = "csiphy", "csiphy_clk_mux";
+ interrupts = <0 80 0>;
+ interrupt-names = "csiphy";
+ gdscr-supply = <&gdsc_camss_top>;
+ bimc_smmu-supply = <&gdsc_bimc_smmu>;
+ qcom,cam-vreg-name = "gdscr", "bimc_smmu";
+ clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
+ <&clock_mmss MMSS_MNOC_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>,
+ <&clock_mmss MMSS_CAMSS_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_TOP_AHB_CLK>,
+ <&clock_mmss CSI2_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSI2_CLK>,
+ <&clock_mmss MMSS_CAMSS_CPHY_CSID2_CLK>,
+ <&clock_mmss CSI2PHYTIMER_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSI2PHYTIMER_CLK>,
+ <&clock_mmss MMSS_CAMSS_ISPIF_AHB_CLK>,
+ <&clock_mmss CSIPHY_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSIPHY2_CLK>,
+ <&clock_mmss MMSS_CSIPHY_AHB2CRIF_CLK>;
+ clock-names = "mmssnoc_axi", "mnoc_ahb",
+ "bmic_smmu_ahb", "bmic_smmu_axi",
+ "camss_ahb_clk", "camss_top_ahb_clk",
+ "csi_src_clk", "csi_clk", "cphy_csid_clk",
+ "csiphy_timer_src_clk", "csiphy_timer_clk",
+ "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk",
+ "csiphy_ahb2crif";
+ qcom,clock-rates = <0 0 0 0 0 0 384000000 0 0 269333333 0
+ 0 384000000 0 0>;
+ status = "ok";
+ };
+
+ qcom,csid@ca30000 {
+ cell-index = <0>;
+ compatible = "qcom,csid-v5.0", "qcom,csid";
+ reg = <0xca30000 0x400>;
+ reg-names = "csid";
+ interrupts = <0 296 0>;
+ interrupt-names = "csid";
+ qcom,csi-vdd-voltage = <1200000>;
+ qcom,mipi-csi-vdd-supply = <&pm660_l1>;
+ gdscr-supply = <&gdsc_camss_top>;
+ vdd_sec-supply = <&pm660l_l1>;
+ bimc_smmu-supply = <&gdsc_bimc_smmu>;
+ qcom,cam-vreg-name = "vdd_sec", "gdscr", "bimc_smmu";
+ qcom,cam-vreg-min-voltage = <925000 0 0>;
+ qcom,cam-vreg-max-voltage = <925000 0 0>;
+ qcom,cam-vreg-op-mode = <0 0 0>;
+ clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
+ <&clock_mmss MMSS_MNOC_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>,
+ <&clock_mmss MMSS_CAMSS_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_TOP_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_ISPIF_AHB_CLK>,
+ <&clock_mmss CSI0_CLK_SRC>,
+ <&clock_mmss CSIPHY_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSI0_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI0_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI0RDI_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI0PIX_CLK>,
+ <&clock_mmss MMSS_CAMSS_CPHY_CSID0_CLK>;
+ clock-names = "mmssnoc_axi", "mnoc_ahb",
+ "bmic_smmu_ahb", "bmic_smmu_axi",
+ "camss_ahb_clk", "camss_top_ahb_clk",
+ "ispif_ahb_clk", "csi_src_clk", "csiphy_clk_src",
+ "csi_clk", "csi_ahb_clk", "csi_rdi_clk",
+ "csi_pix_clk", "cphy_csid_clk";
+ qcom,clock-rates = <0 0 0 0 0 0 0 384000000 384000000
+ 0 0 0 0 0>;
+ status = "ok";
+ };
+
+ qcom,csid@ca30400 {
+ cell-index = <1>;
+ compatible = "qcom,csid-v5.0", "qcom,csid";
+ reg = <0xca30400 0x400>;
+ reg-names = "csid";
+ interrupts = <0 297 0>;
+ interrupt-names = "csid";
+ qcom,csi-vdd-voltage = <1200000>;
+ qcom,mipi-csi-vdd-supply = <&pm660_l1>;
+ gdscr-supply = <&gdsc_camss_top>;
+ vdd_sec-supply = <&pm660l_l1>;
+ bimc_smmu-supply = <&gdsc_bimc_smmu>;
+ qcom,cam-vreg-name = "vdd_sec", "gdscr", "bimc_smmu";
+ qcom,cam-vreg-min-voltage = <925000 0 0>;
+ qcom,cam-vreg-max-voltage = <925000 0 0>;
+ qcom,cam-vreg-op-mode = <0 0 0>;
+ clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
+ <&clock_mmss MMSS_MNOC_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>,
+ <&clock_mmss MMSS_CAMSS_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_TOP_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_ISPIF_AHB_CLK>,
+ <&clock_mmss CSI1_CLK_SRC>,
+ <&clock_mmss CSIPHY_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSI1_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI1_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI1RDI_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI1PIX_CLK>,
+ <&clock_mmss MMSS_CAMSS_CPHY_CSID1_CLK>;
+ clock-names = "mmssnoc_axi", "mnoc_ahb",
+ "bmic_smmu_ahb", "bmic_smmu_axi",
+ "camss_ahb_clk", "camss_top_ahb_clk",
+ "ispif_ahb_clk", "csi_src_clk", "csiphy_clk_src",
+ "csi_clk", "csi_ahb_clk", "csi_rdi_clk",
+ "csi_pix_clk", "cphy_csid_clk";
+ qcom,clock-rates = <0 0 0 0 0 0 0 256000000 256000000
+ 0 0 0 0 0>;
+ status = "ok";
+ };
+
+ qcom,csid@ca30800 {
+ cell-index = <2>;
+ compatible = "qcom,csid-v5.0", "qcom,csid";
+ reg = <0xca30800 0x400>;
+ reg-names = "csid";
+ interrupts = <0 298 0>;
+ interrupt-names = "csid";
+ qcom,csi-vdd-voltage = <1200000>;
+ qcom,mipi-csi-vdd-supply = <&pm660_l1>;
+ gdscr-supply = <&gdsc_camss_top>;
+ vdd_sec-supply = <&pm660l_l1>;
+ bimc_smmu-supply = <&gdsc_bimc_smmu>;
+ qcom,cam-vreg-name = "vdd_sec", "gdscr", "bimc_smmu";
+ qcom,cam-vreg-min-voltage = <925000 0 0>;
+ qcom,cam-vreg-max-voltage = <925000 0 0>;
+ qcom,cam-vreg-op-mode = <0 0 0>;
+ clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
+ <&clock_mmss MMSS_MNOC_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>,
+ <&clock_mmss MMSS_CAMSS_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_TOP_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_ISPIF_AHB_CLK>,
+ <&clock_mmss CSI2_CLK_SRC>,
+ <&clock_mmss CSIPHY_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSI2_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI2_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI2RDI_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI2PIX_CLK>,
+ <&clock_mmss MMSS_CAMSS_CPHY_CSID2_CLK>;
+ clock-names = "mmssnoc_axi", "mnoc_ahb",
+ "bmic_smmu_ahb", "bmic_smmu_axi",
+ "camss_ahb_clk", "camss_top_ahb_clk",
+ "ispif_ahb_clk", "csi_src_clk", "csiphy_clk_src",
+ "csi_clk", "csi_ahb_clk", "csi_rdi_clk",
+ "csi_pix_clk", "cphy_csid_clk";
+ qcom,clock-rates = <0 0 0 0 0 0 0 256000000 256000000
+ 0 0 0 0 0>;
+ status = "ok";
+ };
+
+ qcom,csid@ca30c00 {
+ cell-index = <3>;
+ compatible = "qcom,csid-v5.0", "qcom,csid";
+ reg = <0xca30c00 0x400>;
+ reg-names = "csid";
+ interrupts = <0 299 0>;
+ interrupt-names = "csid";
+ qcom,csi-vdd-voltage = <1200000>;
+ qcom,mipi-csi-vdd-supply = <&pm660_l1>;
+ gdscr-supply = <&gdsc_camss_top>;
+ vdd_sec-supply = <&pm660l_l1>;
+ bimc_smmu-supply = <&gdsc_bimc_smmu>;
+ qcom,cam-vreg-name = "vdd_sec", "gdscr", "bimc_smmu";
+ qcom,cam-vreg-min-voltage = <925000 0 0>;
+ qcom,cam-vreg-max-voltage = <925000 0 0>;
+ qcom,cam-vreg-op-mode = <0 0 0>;
+ clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
+ <&clock_mmss MMSS_MNOC_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>,
+ <&clock_mmss MMSS_CAMSS_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_TOP_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_ISPIF_AHB_CLK>,
+ <&clock_mmss CSI3_CLK_SRC>,
+ <&clock_mmss CSIPHY_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSI3_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI3_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI3RDI_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI3PIX_CLK>,
+ <&clock_mmss MMSS_CAMSS_CPHY_CSID3_CLK>;
+ clock-names = "mmssnoc_axi", "mnoc_ahb",
+ "bmic_smmu_ahb", "bmic_smmu_axi",
+ "camss_ahb_clk", "camss_top_ahb_clk",
+ "ispif_ahb_clk", "csi_src_clk", "csiphy_clk_src",
+ "csi_clk", "csi_ahb_clk", "csi_rdi_clk",
+ "csi_pix_clk", "cphy_csid_clk";
+ qcom,clock-rates = <0 0 0 0 0 0 0 256000000 256000000
+ 0 0 0 0 0>;
+ status = "ok";
+ };
+
+ qcom,cam_smmu {
+ compatible = "qcom,msm-cam-smmu";
+ status = "ok";
+
+ msm_cam_smmu_cb1 {
+ compatible = "qcom,msm-cam-smmu-cb";
+ iommus = <&mmss_bimc_smmu 0xc00>,
+ <&mmss_bimc_smmu 0xc01>,
+ <&mmss_bimc_smmu 0xc02>,
+ <&mmss_bimc_smmu 0xc03>;
+ label = "vfe";
+ qcom,scratch-buf-support;
+ };
+
+ msm_cam_smmu_cb2 {
+ compatible = "qcom,msm-cam-smmu-cb";
+ iommus = <&mmss_bimc_smmu 0xa00>;
+ label = "cpp";
+ };
+
+ msm_cam_smmu_cb4 {
+ compatible = "qcom,msm-cam-smmu-cb";
+ iommus = <&mmss_bimc_smmu 0x800>;
+ label = "jpeg_enc0";
+ };
+
+ msm_cam_smmu_cb5 {
+ compatible = "qcom,msm-cam-smmu-cb";
+ iommus = <&mmss_bimc_smmu 0x801>;
+ label = "jpeg_dma";
+ };
+ };
+
+ qcom,cpp@ca04000 {
+ cell-index = <0>;
+ compatible = "qcom,cpp";
+ reg = <0xca04000 0x100>,
+ <0xca80000 0x3000>,
+ <0xca18000 0x3000>,
+ <0xc8c36D4 0x4>;
+ reg-names = "cpp", "cpp_vbif", "cpp_hw", "camss_cpp";
+ interrupts = <0 294 0>;
+ interrupt-names = "cpp";
+ smmu-vdd-supply = <&gdsc_bimc_smmu>;
+ camss-vdd-supply = <&gdsc_camss_top>;
+ vdd-supply = <&gdsc_cpp>;
+ qcom,vdd-names = "smmu-vdd", "camss-vdd", "vdd";
+ clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
+ <&clock_mmss MMSS_MNOC_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_TOP_AHB_CLK>,
+ <&clock_mmss CPP_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CPP_CLK>,
+ <&clock_mmss MMSS_CAMSS_CPP_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_CPP_AXI_CLK>,
+ <&clock_mmss MMSS_CAMSS_MICRO_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>,
+ <&clock_mmss MMSS_CAMSS_CPP_VBIF_AHB_CLK>;
+ clock-names = "mmssnoc_axi_clk",
+ "mnoc_ahb_clk",
+ "camss_ahb_clk", "camss_top_ahb_clk",
+ "cpp_src_clk",
+ "cpp_core_clk", "camss_cpp_ahb_clk",
+ "camss_cpp_axi_clk", "micro_iface_clk",
+ "mmss_smmu_axi_clk", "cpp_vbif_ahb_clk";
+ qcom,clock-rates = <0 0 0 0 200000000 200000000 0 0 0 0 0>;
+ qcom,min-clock-rate = <200000000>;
+ qcom,bus-master = <1>;
+ qcom,vbif-qos-setting = <0x550 0x55555555>,
+ <0x554 0x55555555>,
+ <0x558 0x55555555>,
+ <0x55c 0x55555555>,
+ <0x560 0x55555555>,
+ <0x564 0x55555555>,
+ <0x568 0x55555555>,
+ <0x56c 0x55555555>,
+ <0x570 0x55555555>,
+ <0x574 0x55555555>,
+ <0x578 0x55555555>,
+ <0x57c 0x55555555>,
+ <0x580 0x55555555>,
+ <0x584 0x55555555>,
+ <0x588 0x55555555>,
+ <0x58c 0x55555555>;
+ status = "ok";
+ qcom,msm-bus,name = "msm_camera_cpp";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <106 512 0 0>,
+ <106 512 0 0>;
+ qcom,msm-bus-vector-dyn-vote;
+ resets = <&clock_mmss CAMSS_MICRO_BCR>;
+ reset-names = "micro_iface_reset";
+ qcom,src-clock-rates = <120000000 256000000 384000000
+ 480000000 540000000 576000000>;
+ qcom,cpp-fw-payload-info {
+ qcom,stripe-base = <790>;
+ qcom,plane-base = <715>;
+ qcom,stripe-size = <63>;
+ qcom,plane-size = <25>;
+ qcom,fe-ptr-off = <11>;
+ qcom,we-ptr-off = <23>;
+ qcom,ref-fe-ptr-off = <17>;
+ qcom,ref-we-ptr-off = <36>;
+ qcom,we-meta-ptr-off = <42>;
+ qcom,fe-mmu-pf-ptr-off = <7>;
+ qcom,ref-fe-mmu-pf-ptr-off = <10>;
+ qcom,we-mmu-pf-ptr-off = <13>;
+ qcom,dup-we-mmu-pf-ptr-off = <18>;
+ qcom,ref-we-mmu-pf-ptr-off = <23>;
+ qcom,set-group-buffer-len = <135>;
+ qcom,dup-frame-indicator-off = <70>;
+ };
+ };
+
+ qcom,ispif@ca31000 {
+ cell-index = <0>;
+ compatible = "qcom,ispif-v3.0", "qcom,ispif";
+ reg = <0xca31000 0xc00>,
+ <0xca00020 0x4>;
+ reg-names = "ispif", "csi_clk_mux";
+ interrupts = <0 309 0>;
+ interrupt-names = "ispif";
+ qcom,num-isps = <0x2>;
+ camss-vdd-supply = <&gdsc_camss_top>;
+ vfe0-vdd-supply = <&gdsc_vfe0>;
+ vfe1-vdd-supply = <&gdsc_vfe1>;
+ qcom,vdd-names = "camss-vdd", "vfe0-vdd",
+ "vfe1-vdd";
+ qcom,clock-cntl-support;
+ clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
+ <&clock_mmss MMSS_MNOC_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_TOP_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_ISPIF_AHB_CLK>,
+ <&clock_mmss CSI0_CLK_SRC>,
+ <&clock_mmss CSI1_CLK_SRC>,
+ <&clock_mmss CSI2_CLK_SRC>,
+ <&clock_mmss CSI3_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSI0RDI_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI1RDI_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI2RDI_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI3RDI_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI0PIX_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI1PIX_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI2PIX_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI3PIX_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI0_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI1_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI2_CLK>,
+ <&clock_mmss MMSS_CAMSS_CSI3_CLK>,
+ <&clock_mmss MMSS_CAMSS_VFE0_CLK>,
+ <&clock_mmss VFE0_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSI_VFE0_CLK>,
+ <&clock_mmss MMSS_CAMSS_VFE1_CLK>,
+ <&clock_mmss VFE1_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSI_VFE1_CLK>;
+ clock-names = "mmssnoc_axi", "mnoc_ahb_clk",
+ "camss_ahb_clk",
+ "camss_top_ahb_clk", "ispif_ahb_clk",
+ "csi0_src_clk", "csi1_src_clk",
+ "csi2_src_clk", "csi3_src_clk",
+ "csi0_rdi_clk", "csi1_rdi_clk",
+ "csi2_rdi_clk", "csi3_rdi_clk",
+ "csi0_pix_clk", "csi1_pix_clk",
+ "csi2_pix_clk", "csi3_pix_clk",
+ "camss_csi0_clk", "camss_csi1_clk",
+ "camss_csi2_clk", "camss_csi3_clk",
+ "camss_vfe_vfe0_clk",
+ "vfe0_clk_src", "camss_csi_vfe0_clk",
+ "camss_vfe_vfe1_clk",
+ "vfe1_clk_src", "camss_csi_vfe1_clk";
+ qcom,clock-rates = <0 0 0 0 0
+ 0 0 0 0
+ 0 0 0 0
+ 0 0 0 0
+ 0 0 0 0
+ 0 0 0
+ 0 0 0>;
+ qcom,clock-control = "INIT_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE",
+ "INIT_RATE", "INIT_RATE",
+ "INIT_RATE", "INIT_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE",
+ "INIT_RATE", "NO_SET_RATE",
+ "NO_SET_RATE",
+ "INIT_RATE", "NO_SET_RATE";
+ status = "ok";
+ };
+
+ vfe0: qcom,vfe0@ca10000 {
+ cell-index = <0>;
+ compatible = "qcom,vfe48";
+ reg = <0xca10000 0x4000>,
+ <0xca40000 0x3000>;
+ reg-names = "vfe", "vfe_vbif";
+ interrupts = <0 314 0>;
+ interrupt-names = "vfe";
+ vdd-supply = <&gdsc_vfe0>;
+ camss-vdd-supply = <&gdsc_camss_top>;
+ smmu-vdd-supply = <&gdsc_bimc_smmu>;
+ qcom,vdd-names = "vdd", "camss-vdd", "smmu-vdd";
+ clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
+ <&clock_mmss MMSS_MNOC_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>,
+ <&clock_mmss MMSS_CAMSS_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_TOP_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_VFE0_CLK>,
+ <&clock_mmss MMSS_CAMSS_VFE0_STREAM_CLK>,
+ <&clock_mmss MMSS_CAMSS_VFE0_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_VFE_VBIF_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_VFE_VBIF_AXI_CLK>,
+ <&clock_mmss VFE0_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSI_VFE0_CLK>;
+ clock-names = "mmssnoc_axi", "mnoc_ahb_clk",
+ "bimc_smmu_ahb_clk", "bimc_smmu_axi_clk",
+ "camss_ahb_clk", "camss_top_ahb_clk",
+ "camss_vfe_clk", "camss_vfe_stream_clk",
+ "camss_vfe_ahb_clk", "camss_vfe_vbif_ahb_clk",
+ "camss_vfe_vbif_axi_clk", "vfe_clk_src",
+ "camss_csi_vfe_clk";
+ qcom,clock-rates = <0 0 0 0 0 0 0 0 0 0 0 256000000 0
+ 0 0 0 0 0 0 0 0 0 0 0 480000000 0
+ 0 0 0 0 0 0 0 0 0 0 0 576000000 0>;
+ status = "ok";
+ qos-entries = <8>;
+ qos-regs = <0x404 0x408 0x40c 0x410 0x414 0x418
+ 0x41c 0x420>;
+ qos-settings = <0xaaa5aaa5
+ 0xaaa5aaa5
+ 0xaaa5aaa5
+ 0xaa55aaa5
+ 0xaa55aa55
+ 0xaa55aa55
+ 0xaa55aa55
+ 0x0005aa55>;
+ vbif-entries = <3>;
+ vbif-regs = <0x124 0xac 0xd0>;
+ vbif-settings = <0x3 0x40 0x1010>;
+ ds-entries = <17>;
+ ds-regs = <0x424 0x428 0x42c 0x430 0x434
+ 0x438 0x43c 0x440 0x444 0x448 0x44c
+ 0x450 0x454 0x458 0x45c 0x460 0x464>;
+ ds-settings = <0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0x110>;
+ qcom,msm-bus,name = "msm_camera_vfe";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <29 512 0 0>,
+ <29 512 100000000 100000000>;
+ qcom,msm-bus-vector-dyn-vote;
+ };
+
+ vfe1: qcom,vfe1@ca14000 {
+ cell-index = <1>;
+ compatible = "qcom,vfe48";
+ reg = <0xca14000 0x4000>,
+ <0xca40000 0x3000>;
+ reg-names = "vfe", "vfe_vbif";
+ interrupts = <0 315 0>;
+ interrupt-names = "vfe";
+ vdd-supply = <&gdsc_vfe1>;
+ camss-vdd-supply = <&gdsc_camss_top>;
+ smmu-vdd-supply = <&gdsc_bimc_smmu>;
+ qcom,vdd-names = "vdd", "camss-vdd", "smmu-vdd";
+ clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
+ <&clock_mmss MMSS_MNOC_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>,
+ <&clock_mmss MMSS_CAMSS_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_TOP_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_VFE1_CLK>,
+ <&clock_mmss MMSS_CAMSS_VFE1_STREAM_CLK>,
+ <&clock_mmss MMSS_CAMSS_VFE1_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_VFE_VBIF_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_VFE_VBIF_AXI_CLK>,
+ <&clock_mmss VFE1_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CSI_VFE1_CLK>;
+ clock-names = "mmssnoc_axi", "mnoc_ahb_clk",
+ "bimc_smmu_ahb_clk", "bimc_smmu_axi_clk",
+ "camss_ahb_clk", "camss_top_ahb_clk",
+ "camss_vfe_clk", "camss_vfe_stream_clk",
+ "camss_vfe_ahb_clk", "camss_vfe_vbif_ahb_clk",
+ "camss_vfe_vbif_axi_clk", "vfe_clk_src",
+ "camss_csi_vfe_clk";
+ qcom,clock-rates = <0 0 0 0 0 0 0 0 0 0 0 256000000 0
+ 0 0 0 0 0 0 0 0 0 0 0 480000000 0
+ 0 0 0 0 0 0 0 0 0 0 0 576000000 0>;
+ status = "ok";
+ qos-entries = <8>;
+ qos-regs = <0x404 0x408 0x40c 0x410 0x414 0x418
+ 0x41c 0x420>;
+ qos-settings = <0xaaa5aaa5
+ 0xaaa5aaa5
+ 0xaaa5aaa5
+ 0xaa55aaa5
+ 0xaa55aa55
+ 0xaa55aa55
+ 0xaa55aa55
+ 0x0005aa55>;
+ vbif-entries = <3>;
+ vbif-regs = <0x124 0xac 0xd0>;
+ vbif-settings = <0x3 0x40 0x1010>;
+ ds-entries = <17>;
+ ds-regs = <0x424 0x428 0x42c 0x430 0x434
+ 0x438 0x43c 0x440 0x444 0x448 0x44c
+ 0x450 0x454 0x458 0x45c 0x460 0x464>;
+ ds-settings = <0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0xcccc1111
+ 0x110>;
+ qcom,msm-bus,name = "msm_camera_vfe";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <29 512 0 0>,
+ <29 512 100000000 100000000>;
+ qcom,msm-bus-vector-dyn-vote;
+ };
+
+ qcom,vfe {
+ compatible = "qcom,vfe";
+ num_child = <2>;
+ };
+
+ cci: qcom,cci@ca0c000 {
+ cell-index = <0>;
+ compatible = "qcom,cci";
+ reg = <0xca0c000 0x4000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "cci";
+ interrupts = <0 295 0>;
+ interrupt-names = "cci";
+ status = "ok";
+ mmagic-supply = <&gdsc_bimc_smmu>;
+ gdscr-supply = <&gdsc_camss_top>;
+ qcom,cam-vreg-name = "mmagic", "gdscr";
+ clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
+ <&clock_mmss MMSS_MNOC_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>,
+ <&clock_mmss MMSS_CAMSS_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_TOP_AHB_CLK>,
+ <&clock_mmss CCI_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_CCI_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_CCI_CLK>;
+ clock-names = "mmssnoc_axi", "mnoc_ahb", "smmu_ahb", "smmu_axi",
+ "camss_ahb_clk", "camss_top_ahb_clk",
+ "cci_src_clk", "cci_ahb_clk", "camss_cci_clk";
+ qcom,clock-rates = <0 0 0 0 0 0 19200000 0 0>,
+ <0 0 0 0 0 0 37500000 0 0>;
+ pinctrl-names = "cci_default", "cci_suspend";
+ pinctrl-0 = <&cci0_active &cci1_active>;
+ pinctrl-1 = <&cci0_suspend &cci1_suspend>;
+ gpios = <&tlmm 36 0>,
+ <&tlmm 37 0>,
+ <&tlmm 38 0>,
+ <&tlmm 39 0>;
+ qcom,gpio-tbl-num = <0 1 2 3>;
+ qcom,gpio-tbl-flags = <1 1 1 1>;
+ qcom,gpio-tbl-label = "CCI_I2C_DATA0",
+ "CCI_I2C_CLK0",
+ "CCI_I2C_DATA1",
+ "CCI_I2C_CLK1";
+ i2c_freq_100Khz: qcom,i2c_standard_mode {
+ status = "disabled";
+ };
+ i2c_freq_400Khz: qcom,i2c_fast_mode {
+ status = "disabled";
+ };
+ i2c_freq_custom: qcom,i2c_custom_mode {
+ status = "disabled";
+ };
+ i2c_freq_1Mhz: qcom,i2c_fast_plus_mode {
+ status = "disabled";
+ };
+ };
+
+ qcom,jpeg@ca1c000 {
+ cell-index = <0>;
+ compatible = "qcom,jpeg";
+ reg = <0xca1c000 0x4000>,
+ <0xca60000 0x3000>;
+ reg-names = "jpeg_hw", "jpeg_vbif";
+ interrupts = <0 316 0>;
+ interrupt-names = "jpeg";
+ smmu-vdd-supply = <&gdsc_bimc_smmu>;
+ camss-vdd-supply = <&gdsc_camss_top>;
+ qcom,vdd-names = "smmu-vdd", "camss-vdd";
+ clock-names = "mmssnoc_axi",
+ "mmss_mnoc_ahb_clk",
+ "mmss_bimc_smmu_ahb_clk",
+ "mmss_bimc_smmu_axi_clk",
+ "mmss_camss_ahb_clk",
+ "mmss_camss_top_ahb_clk",
+ "core_clk",
+ "mmss_camss_jpeg_ahb_clk",
+ "mmss_camss_jpeg_axi_clk";
+ clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
+ <&clock_mmss MMSS_MNOC_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>,
+ <&clock_mmss MMSS_CAMSS_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_TOP_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_JPEG0_VOTE_CLK>,
+ <&clock_mmss MMSS_CAMSS_JPEG_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_JPEG_AXI_CLK >;
+ qcom,clock-rates = <0 0 0 0 0 0 480000000 0 0>;
+ qcom,vbif-reg-settings = <0x4 0x1>;
+ qcom,prefetch-reg-settings = <0x30c 0x1111>,
+ <0x318 0x31>,
+ <0x324 0x31>,
+ <0x330 0x31>,
+ <0x33c 0x0>;
+ qcom,msm-bus,name = "msm_camera_jpeg0";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <62 512 0 0>,
+ <62 512 1920000 2880000>;
+ status = "ok";
+ };
+
+ qcom,jpeg@caa0000 {
+ cell-index = <3>;
+ compatible = "qcom,jpegdma";
+ reg = <0xcaa0000 0x4000>,
+ <0xca60000 0x3000>;
+ reg-names = "jpeg_hw", "jpeg_vbif";
+ interrupts = <0 304 0>;
+ interrupt-names = "jpeg";
+ smmu-vdd-supply = <&gdsc_bimc_smmu>;
+ camss-vdd-supply = <&gdsc_camss_top>;
+ qcom,vdd-names = "smmu-vdd", "camss-vdd";
+ clock-names = "mmssnoc_axi",
+ "mmss_mnoc_ahb_clk",
+ "mmss_bimc_smmu_ahb_clk",
+ "mmss_bimc_smmu_axi_clk",
+ "mmss_camss_ahb_clk",
+ "mmss_camss_top_ahb_clk",
+ "core_clk",
+ "mmss_camss_jpeg_ahb_clk",
+ "mmss_camss_jpeg_axi_clk";
+ clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
+ <&clock_mmss MMSS_MNOC_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>,
+ <&clock_mmss MMSS_CAMSS_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_TOP_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_JPEG0_DMA_VOTE_CLK>,
+ <&clock_mmss MMSS_CAMSS_JPEG_AHB_CLK>,
+ <&clock_mmss MMSS_CAMSS_JPEG_AXI_CLK>;
+ qcom,clock-rates = <0 0 0 0 0 0 480000000 0 0>;
+ qcom,vbif-reg-settings = <0x4 0x1>;
+ qcom,prefetch-reg-settings = <0x18c 0x11>,
+ <0x1a0 0x31>,
+ <0x1b0 0x31>;
+ qcom,msm-bus,name = "msm_camera_jpeg_dma";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <62 512 0 0>,
+ <62 512 1920000 2880000>;
+ qcom,max-ds-factor = <128>;
+ status = "ok";
+ };
+};
+
+&i2c_freq_100Khz {
+ qcom,hw-thigh = <201>;
+ qcom,hw-tlow = <174>;
+ qcom,hw-tsu-sto = <204>;
+ qcom,hw-tsu-sta = <231>;
+ qcom,hw-thd-dat = <22>;
+ qcom,hw-thd-sta = <162>;
+ qcom,hw-tbuf = <227>;
+ qcom,hw-scl-stretch-en = <0>;
+ qcom,hw-trdhld = <6>;
+ qcom,hw-tsp = <3>;
+ qcom,cci-clk-src = <37500000>;
+ status = "ok";
+};
+
+&i2c_freq_400Khz {
+ qcom,hw-thigh = <38>;
+ qcom,hw-tlow = <56>;
+ qcom,hw-tsu-sto = <40>;
+ qcom,hw-tsu-sta = <40>;
+ qcom,hw-thd-dat = <22>;
+ qcom,hw-thd-sta = <35>;
+ qcom,hw-tbuf = <62>;
+ qcom,hw-scl-stretch-en = <0>;
+ qcom,hw-trdhld = <6>;
+ qcom,hw-tsp = <3>;
+ qcom,cci-clk-src = <37500000>;
+ status = "ok";
+};
+
+&i2c_freq_custom {
+ qcom,hw-thigh = <38>;
+ qcom,hw-tlow = <56>;
+ qcom,hw-tsu-sto = <40>;
+ qcom,hw-tsu-sta = <40>;
+ qcom,hw-thd-dat = <22>;
+ qcom,hw-thd-sta = <35>;
+ qcom,hw-tbuf = <62>;
+ qcom,hw-scl-stretch-en = <1>;
+ qcom,hw-trdhld = <6>;
+ qcom,hw-tsp = <3>;
+ qcom,cci-clk-src = <37500000>;
+ status = "ok";
+};
+
+&i2c_freq_1Mhz {
+ qcom,hw-thigh = <16>;
+ qcom,hw-tlow = <22>;
+ qcom,hw-tsu-sto = <17>;
+ qcom,hw-tsu-sta = <18>;
+ qcom,hw-thd-dat = <16>;
+ qcom,hw-thd-sta = <15>;
+ qcom,hw-tbuf = <24>;
+ qcom,hw-scl-stretch-en = <0>;
+ qcom,hw-trdhld = <3>;
+ qcom,hw-tsp = <3>;
+ qcom,cci-clk-src = <37500000>;
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi b/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
index d223197ad878..060923a5f227 100644
--- a/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
@@ -11,7 +11,7 @@
*/
#include "sdm660-pinctrl.dtsi"
-#include "sdm660-camera-sensor-cdp.dtsi"
+#include "sdm630-camera-sensor-cdp.dtsi"
/ {
};
diff --git a/arch/arm/boot/dts/qcom/sdm630-headset-jacktype-no-cdp.dts b/arch/arm/boot/dts/qcom/sdm630-headset-jacktype-no-cdp.dts
new file mode 100644
index 000000000000..4db377dc755a
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdm630-headset-jacktype-no-cdp.dts
@@ -0,0 +1,26 @@
+/* Copyright (c) 2017, 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.
+ */
+
+
+/dts-v1/;
+
+#include "sdm630.dtsi"
+#include "sdm630-cdp.dtsi"
+#include "sdm660-external-codec.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM 630 PM660 + PM660L, Headset Jacktype NO, CDP";
+ compatible = "qcom,sdm630-cdp", "qcom,sdm630", "qcom,cdp";
+ qcom,board-id = <1 2>;
+ qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+ <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-headset-jacktype-no-rcm.dts b/arch/arm/boot/dts/qcom/sdm630-headset-jacktype-no-rcm.dts
new file mode 100644
index 000000000000..be30eb172176
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdm630-headset-jacktype-no-rcm.dts
@@ -0,0 +1,26 @@
+/* Copyright (c) 2017, 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.
+ */
+
+
+/dts-v1/;
+
+#include "sdm630.dtsi"
+#include "sdm630-cdp.dtsi"
+#include "sdm660-external-codec.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM 630 PM660 + PM660L, Headset Jacktype NO, RCM";
+ compatible = "qcom,sdm630-cdp", "qcom,sdm630", "qcom,cdp";
+ qcom,board-id = <21 2>;
+ qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+ <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi
index a07118486322..3c19dc70e7c4 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi
@@ -22,7 +22,7 @@
qcom,panel-supply-entry@0 {
reg = <0>;
qcom,supply-name = "wqhd-vddio";
- qcom,supply-min-voltage = <1880000>;
+ qcom,supply-min-voltage = <1800000>;
qcom,supply-max-voltage = <1950000>;
qcom,supply-enable-load = <32000>;
qcom,supply-disable-load = <80>;
diff --git a/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi
index d236dbbad7ec..18e6445b68e1 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi
@@ -62,7 +62,7 @@
qcom,max-bandwidth-per-pipe-kbps = <1 3200000>, /* Default */
<2 2400000>; /* Camera */
qcom,max-clk-rate = <412500000>;
- qcom,mdss-default-ot-rd-limit = <40>;
+ qcom,mdss-default-ot-rd-limit = <32>;
qcom,mdss-default-ot-wr-limit = <32>;
qcom,mdss-dram-channels = <2>;
@@ -480,7 +480,7 @@
qcom,mdss-rot-vbif-qos-setting = <1 1 1 1>;
qcom,mdss-rot-xin-id = <14 15>;
- qcom,mdss-default-ot-rd-limit = <40>;
+ qcom,mdss-default-ot-rd-limit = <32>;
qcom,mdss-default-ot-wr-limit = <32>;
};
};
diff --git a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
index cdcea7654e3e..69dcb26c42a2 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
@@ -11,7 +11,7 @@
*/
#include "sdm660-pinctrl.dtsi"
-#include "sdm660-camera-sensor-mtp.dtsi"
+#include "sdm630-camera-sensor-mtp.dtsi"
/ {
mtp_batterydata: qcom,battery-data {
qcom,batt-id-range-pct = <15>;
diff --git a/arch/arm/boot/dts/qcom/sdm630-pm660a-headset-jacktype-no-cdp.dts b/arch/arm/boot/dts/qcom/sdm630-pm660a-headset-jacktype-no-cdp.dts
new file mode 100644
index 000000000000..15936f47da7b
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdm630-pm660a-headset-jacktype-no-cdp.dts
@@ -0,0 +1,26 @@
+/* Copyright (c) 2017, 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.
+ */
+
+
+/dts-v1/;
+
+#include "sdm630.dtsi"
+#include "sdm630-cdp.dtsi"
+#include "msm-pm660a.dtsi"
+#include "sdm660-external-codec.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM 630 PM660 + PM660A, Headset Jacktype NO, CDP";
+ compatible = "qcom,sdm630-cdp", "qcom,sdm630", "qcom,cdp";
+ qcom,board-id = <1 2>;
+ qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-pm660a-headset-jacktype-no-rcm.dts b/arch/arm/boot/dts/qcom/sdm630-pm660a-headset-jacktype-no-rcm.dts
new file mode 100644
index 000000000000..aeba192834f3
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdm630-pm660a-headset-jacktype-no-rcm.dts
@@ -0,0 +1,26 @@
+/* Copyright (c) 2017, 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.
+ */
+
+
+/dts-v1/;
+
+#include "sdm630.dtsi"
+#include "sdm630-cdp.dtsi"
+#include "msm-pm660a.dtsi"
+#include "sdm660-external-codec.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM 630 PM660 + PM660A, Headset Jacktype NO, RCM";
+ compatible = "qcom,sdm630-cdp", "qcom,sdm630", "qcom,cdp";
+ qcom,board-id = <21 2>;
+ qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
index b1fed582aa1e..f80562e22989 100644
--- a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
@@ -123,6 +123,18 @@
};
};
+&pm660_gpios {
+ /* GPIO 11 for home key */
+ gpio@ca00 {
+ status = "ok";
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <0>;
+ qcom,src-sel = <0>;
+ qcom,out-strength = <1>;
+ };
+};
+
&soc {
gpio_keys {
compatible = "gpio-keys";
@@ -137,5 +149,15 @@
gpio-key,wakeup;
debounce-interval = <15>;
};
+
+ home {
+ label = "home";
+ gpios = <&pm660_gpios 11 0x1>;
+ linux,input-type = <1>;
+ linux,code = <102>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+
};
};
diff --git a/arch/arm/boot/dts/qcom/sdm630-regulator.dtsi b/arch/arm/boot/dts/qcom/sdm630-regulator.dtsi
index d53ac2f48c0c..13b561944e13 100644
--- a/arch/arm/boot/dts/qcom/sdm630-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-regulator.dtsi
@@ -383,7 +383,7 @@
rpm-regulator-ldob8 {
status = "okay";
pm660l_l8: regulator-l8 {
- regulator-min-microvolt = <3200000>;
+ regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <3400000>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi
index f6baee79dcbc..3b262453c0ed 100644
--- a/arch/arm/boot/dts/qcom/sdm630.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630.dtsi
@@ -953,7 +953,7 @@
};
clock_mmss: clock-controller@c8c0000 {
- compatible = "qcom,mmcc-sdm660";
+ compatible = "qcom,mmcc-sdm630";
reg = <0xc8c0000 0x40000>;
vdd_mx_mmss-supply = <&pm660l_s5_level>;
vdd_dig_mmss-supply = <&pm660l_s3_level>;
@@ -1249,13 +1249,15 @@
clock_cpu: qcom,clk-cpu-630@179c0000 {
compatible = "qcom,clk-cpu-osm-sdm630";
- status = "disabled";
reg = <0x179c0000 0x4000>, <0x17916000 0x1000>,
<0x17816000 0x1000>, <0x179d1000 0x1000>,
<0x00784130 0x8>;
reg-names = "osm", "pwrcl_pll", "perfcl_pll",
"apcs_common", "perfcl_efuse";
+ vdd-pwrcl-supply = <&apc0_pwrcl_vreg>;
+ vdd-perfcl-supply = <&apc1_perfcl_vreg>;
+
interrupts = <GIC_SPI 35 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 36 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "pwrcl-irq", "perfcl-irq";
@@ -1595,11 +1597,13 @@
};
qcom,icnss@18800000 {
- status = "disabled";
compatible = "qcom,icnss";
reg = <0x18800000 0x800000>,
- <0x10ac000 0x20>;
- reg-names = "membase", "mpm_config";
+ <0xa0000000 0x10000000>,
+ <0xb0000000 0x10000>;
+ reg-names = "membase", "smmu_iova_base", "smmu_iova_ipa";
+ iommus = <&anoc2_smmu 0x1a00>,
+ <&anoc2_smmu 0x1a01>;
interrupts = <0 413 0>, /* CE0 */
<0 414 0>, /* CE1 */
<0 415 0>, /* CE2 */
@@ -2068,7 +2072,7 @@
#include "msm-audio.dtsi"
#include "sdm660-audio.dtsi"
#include "sdm630-gpu.dtsi"
-#include "sdm660-camera.dtsi"
+#include "sdm630-camera.dtsi"
#include "sdm630-pm.dtsi"
#include "sdm660-vidc.dtsi"
#include "sdm630-mdss.dtsi"
diff --git a/arch/arm/boot/dts/qcom/sdm660-audio.dtsi b/arch/arm/boot/dts/qcom/sdm660-audio.dtsi
index 8e020ba75ea3..62bab62d74dd 100644
--- a/arch/arm/boot/dts/qcom/sdm660-audio.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-audio.dtsi
@@ -102,6 +102,8 @@
status = "disabled";
compatible = "qcom,pmic-analog-codec";
reg = <0xf000 0x200>;
+ #address-cells = <2>;
+ #size-cells = <0>;
interrupt-parent = <&spmi_bus>;
interrupts = <0x3 0xf0 0x0 IRQ_TYPE_NONE>,
<0x3 0xf0 0x1 IRQ_TYPE_NONE>,
diff --git a/arch/arm/boot/dts/qcom/sdm660-camera.dtsi b/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
index d6a3a143d304..10afca1c56ed 100644
--- a/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
@@ -530,7 +530,7 @@
"camss_vfe_ahb_clk", "camss_vfe_vbif_ahb_clk",
"camss_vfe_vbif_axi_clk", "vfe_clk_src",
"camss_csi_vfe_clk";
- qcom,clock-rates = <0 0 0 0 0 0 0 0 0 0 0 256000000 0
+ qcom,clock-rates = <0 0 0 0 0 0 0 0 0 0 0 404000000 0
0 0 0 0 0 0 0 0 0 0 0 480000000 0
0 0 0 0 0 0 0 0 0 0 0 576000000 0>;
status = "ok";
@@ -610,7 +610,7 @@
"camss_vfe_ahb_clk", "camss_vfe_vbif_ahb_clk",
"camss_vfe_vbif_axi_clk", "vfe_clk_src",
"camss_csi_vfe_clk";
- qcom,clock-rates = <0 0 0 0 0 0 0 0 0 0 0 256000000 0
+ qcom,clock-rates = <0 0 0 0 0 0 0 0 0 0 0 404000000 0
0 0 0 0 0 0 0 0 0 0 0 480000000 0
0 0 0 0 0 0 0 0 0 0 0 576000000 0>;
status = "ok";
diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
index 0fc24dc6e72b..9c3862ce6a1f 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
@@ -133,10 +133,6 @@
23 18 07 08 04 03 04 a0];
qcom,esd-check-enabled;
qcom,mdss-dsi-panel-status-check-mode = "bta_check";
- qcom,mdss-dsi-min-refresh-rate = <53>;
- qcom,mdss-dsi-max-refresh-rate = <60>;
- qcom,mdss-dsi-pan-enable-dynamic-fps;
- qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
};
&dsi_dual_nt35597_truly_cmd {
diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi
index 8116f56642f3..fd07a105a19a 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi
@@ -61,7 +61,7 @@
qcom,max-bandwidth-high-kbps = <6600000>;
qcom,max-bandwidth-per-pipe-kbps = <3100000>;
qcom,max-clk-rate = <412500000>;
- qcom,mdss-default-ot-rd-limit = <40>;
+ qcom,mdss-default-ot-rd-limit = <32>;
qcom,mdss-default-ot-wr-limit = <32>;
qcom,mdss-dram-channels = <2>;
@@ -577,7 +577,7 @@
qcom,mdss-rot-vbif-qos-setting = <1 1 1 1>;
qcom,mdss-rot-xin-id = <14 15>;
- qcom,mdss-default-ot-rd-limit = <40>;
+ qcom,mdss-default-ot-rd-limit = <32>;
qcom,mdss-default-ot-wr-limit = <32>;
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-mtp.dtsi b/arch/arm/boot/dts/qcom/sdm660-mtp.dtsi
index 24bab18cd750..941fe808188c 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-mtp.dtsi
@@ -251,6 +251,6 @@
qcom,parallel-charger;
qcom,float-voltage-mv = <4400>;
qcom,recharge-mv = <100>;
- qcom,parallel-en-pin-polarity = <0>;
+ qcom,parallel-en-pin-polarity = <1>;
};
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi
index 49b58c8be8d5..1db65c064f66 100644
--- a/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi
@@ -107,6 +107,9 @@
};
&soc {
+ qcom,msm-ssc-sensors {
+ compatible = "qcom,msm-ssc-sensors";
+ };
};
&pm660_gpios {
diff --git a/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi b/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi
index 44796eeb7059..47db57b3dc0a 100644
--- a/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi
@@ -672,6 +672,9 @@
qcom,cpr-panic-reg-name-list =
"PWR_CPRH_STATUS", "APCLUS0_L2_SAW4_PMIC_STS";
+ qcom,cpr-enable;
+ qcom,cpr-hw-closed-loop;
+
thread@0 {
qcom,cpr-thread-id = <0>;
qcom,cpr-consecutive-up = <0>;
@@ -707,6 +710,33 @@
qcom,allow-voltage-interpolation;
qcom,allow-quotient-interpolation;
qcom,cpr-scaled-open-loop-voltage-as-ceiling;
+
+ qcom,cpr-ro-scaling-factor =
+ <3600 3600 3830 2430 2520 2700 1790
+ 1760 1970 1880 2110 2010 2510 4900
+ 4370 4780>,
+ <3600 3600 3830 2430 2520 2700 1790
+ 1760 1970 1880 2110 2010 2510 4900
+ 4370 4780>,
+ <3600 3600 3830 2430 2520 2700 1790
+ 1760 1970 1880 2110 2010 2510 4900
+ 4370 4780>,
+ <3600 3600 3830 2430 2520 2700 1790
+ 1760 1970 1880 2110 2010 2510 4900
+ 4370 4780>,
+ <3600 3600 3830 2430 2520 2700 1790
+ 1760 1970 1880 2110 2010 2510 4900
+ 4370 4780>;
+
+ qcom,cpr-open-loop-voltage-fuse-adjustment =
+ <13000 31000 27000 37000 21000>;
+
+ qcom,cpr-closed-loop-voltage-fuse-adjustment =
+ <0 0 0 0 8000>;
+
+ qcom,cpr-floor-to-ceiling-max-range =
+ <32000 32000 32000 40000 40000
+ 40000 40000 40000>;
};
};
};
@@ -747,6 +777,9 @@
qcom,cpr-panic-reg-name-list =
"PERF_CPRH_STATUS", "APCLUS1_L2_SAW4_PMIC_STS";
+ qcom,cpr-enable;
+ qcom,cpr-hw-closed-loop;
+
thread@0 {
qcom,cpr-thread-id = <0>;
qcom,cpr-consecutive-up = <0>;
@@ -788,6 +821,33 @@
qcom,allow-voltage-interpolation;
qcom,allow-quotient-interpolation;
qcom,cpr-scaled-open-loop-voltage-as-ceiling;
+
+ qcom,cpr-ro-scaling-factor =
+ <4040 4230 0000 2210 2560 2450 2230
+ 2220 2410 2300 2560 2470 1600 3120
+ 2620 2280>,
+ <4040 4230 0000 2210 2560 2450 2230
+ 2220 2410 2300 2560 2470 1600 3120
+ 2620 2280>,
+ <4040 4230 0000 2210 2560 2450 2230
+ 2220 2410 2300 2560 2470 1600 3120
+ 2620 2280>,
+ <4040 4230 0000 2210 2560 2450 2230
+ 2220 2410 2300 2560 2470 1600 3120
+ 2620 2280>,
+ <4040 4230 0000 2210 2560 2450 2230
+ 2220 2410 2300 2560 2470 1600 3120
+ 2620 2280>;
+
+ qcom,cpr-open-loop-voltage-fuse-adjustment =
+ <31000 39000 53000 40000 29000>;
+
+ qcom,cpr-closed-loop-voltage-fuse-adjustment =
+ <0 3000 19000 23000 28000>;
+
+ qcom,cpr-floor-to-ceiling-max-range =
+ <40000 40000 40000 40000
+ 40000 40000 40000>;
};
};
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-vidc.dtsi b/arch/arm/boot/dts/qcom/sdm660-vidc.dtsi
index 5f8def7d233f..b1ca93b9f613 100644
--- a/arch/arm/boot/dts/qcom/sdm660-vidc.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-vidc.dtsi
@@ -28,6 +28,7 @@
qcom,firmware-name = "venus";
qcom,never-unload-fw;
qcom,sw-power-collapse;
+ qcom,max-secure-instances = <5>;
qcom,reg-presets =
<0x80010 0x001f001f>,
<0x80018 0x00000156>,
diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi
index 544f04a9f4fe..45244f2bbfc8 100644
--- a/arch/arm/boot/dts/qcom/sdm660.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660.dtsi
@@ -619,7 +619,7 @@
interrupts = <0 184 0>, <0 430 0>;
interrupt-names = "tsens-upper-lower", "tsens-critical";
qcom,client-id = <0 1 2 3 4 5 6 7 8 9 10 11 12 13>;
- qcom,sensor-id = <0 10 11 4 5 6 7 8 13 1 3 12 9 2>;
+ qcom,sensor-id = <0 10 11 4 5 6 7 8 13 2 3 12 9 1>;
qcom,sensors = <14>;
qcom,slope = <3200 3200 3200 3200 3200 3200 3200 3200
3200 3200 3200 3200 3200 3200>;
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index f64ca9a07c6e..80030b40a89b 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -287,6 +287,8 @@ CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v21=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y
CONFIG_SECURE_TOUCH=y
+CONFIG_TOUCHSCREEN_ST=y
+CONFIG_TOUCHSCREEN_ST_I2C=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_QPNP_POWER_ON=y
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index f08cd3b27c81..a118a7a9cf51 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -289,6 +289,8 @@ CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v21=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y
CONFIG_SECURE_TOUCH=y
+CONFIG_TOUCHSCREEN_ST=y
+CONFIG_TOUCHSCREEN_ST_I2C=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_QPNP_POWER_ON=y
diff --git a/certs/Makefile b/certs/Makefile
index 28ac694dd11a..f30d601f410c 100644
--- a/certs/Makefile
+++ b/certs/Makefile
@@ -17,6 +17,10 @@ AFLAGS_system_certificates.o := -I$(srctree)
quiet_cmd_extract_certs = EXTRACT_CERTS $(patsubst "%",%,$(2))
cmd_extract_certs = scripts/extract-cert $(2) $@ || ( rm $@; exit 1)
+ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYS),"verity.x509.pem")
+SYSTEM_TRUSTED_KEYS_SRCPREFIX := $(srctree)/certs/
+endif
+
targets += x509_certificate_list
$(obj)/x509_certificate_list: scripts/extract-cert $(SYSTEM_TRUSTED_KEYS_SRCPREFIX)$(SYSTEM_TRUSTED_KEYS_FILENAME) FORCE
$(call if_changed,extract_certs,$(SYSTEM_TRUSTED_KEYS_SRCPREFIX)$(CONFIG_SYSTEM_TRUSTED_KEYS))
diff --git a/certs/verity.x509.pem b/certs/verity.x509.pem
new file mode 100644
index 000000000000..86399c3c1dd7
--- /dev/null
+++ b/certs/verity.x509.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIID/TCCAuWgAwIBAgIJAJcPmDkJqolJMA0GCSqGSIb3DQEBBQUAMIGUMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g
+VmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UE
+AwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
+Fw0xNDExMDYxOTA3NDBaFw00MjAzMjQxOTA3NDBaMIGUMQswCQYDVQQGEwJVUzET
+MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G
+A1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UEAwwHQW5kcm9p
+ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAOjreE0vTVSRenuzO9vnaWfk0eQzYab0gqpi
+6xAzi6dmD+ugoEKJmbPiuE5Dwf21isZ9uhUUu0dQM46dK4ocKxMRrcnmGxydFn6o
+fs3ODJMXOkv2gKXL/FdbEPdDbxzdu8z3yk+W67udM/fW7WbaQ3DO0knu+izKak/3
+T41c5uoXmQ81UNtAzRGzGchNVXMmWuTGOkg6U+0I2Td7K8yvUMWhAWPPpKLtVH9r
+AL5TzjYNR92izdKcz3AjRsI3CTjtpiVABGeX0TcjRSuZB7K9EK56HV+OFNS6I1NP
+jdD7FIShyGlqqZdUOkAUZYanbpgeT5N7QL6uuqcGpoTOkalu6kkCAwEAAaNQME4w
+HQYDVR0OBBYEFH5DM/m7oArf4O3peeKO0ZIEkrQPMB8GA1UdIwQYMBaAFH5DM/m7
+oArf4O3peeKO0ZIEkrQPMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB
+AHO3NSvDE5jFvMehGGtS8BnFYdFKRIglDMc4niWSzhzOVYRH4WajxdtBWc5fx0ix
+NF/+hVKVhP6AIOQa+++sk+HIi7RvioPPbhjcsVlZe7cUEGrLSSveGouQyc+j0+m6
+JF84kszIl5GGNMTnx0XRPO+g8t6h5LWfnVydgZfpGRRg+WHewk1U2HlvTjIceb0N
+dcoJ8WKJAFWdcuE7VIm4w+vF/DYX/A2Oyzr2+QRhmYSv1cusgAeC1tvH4ap+J1Lg
+UnOu5Kh/FqPLLSwNVQp4Bu7b9QFfqK8Moj84bj88NqRGZgDyqzuTrFxn6FW7dmyA
+yttuAJAEAymk1mipd9+zp38=
+-----END CERTIFICATE-----
diff --git a/drivers/bluetooth/btfm_slim.c b/drivers/bluetooth/btfm_slim.c
index 37cc6284cf97..969f755f5dc4 100644
--- a/drivers/bluetooth/btfm_slim.c
+++ b/drivers/bluetooth/btfm_slim.c
@@ -127,7 +127,7 @@ int btfm_slim_enable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch,
if (!btfmslim || !ch)
return -EINVAL;
- BTFMSLIM_DBG("port:%d", ch->port);
+ BTFMSLIM_DBG("port: %d ch: %d", ch->port, ch->ch);
/* Define the channel with below parameters */
prop.prot = SLIM_AUTO_ISO;
diff --git a/drivers/bluetooth/btfm_slim.h b/drivers/bluetooth/btfm_slim.h
index dbb4c563d802..5d105fba2193 100644
--- a/drivers/bluetooth/btfm_slim.h
+++ b/drivers/bluetooth/btfm_slim.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, 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
@@ -13,7 +13,7 @@
#define BTFM_SLIM_H
#include <linux/slimbus/slimbus.h>
-#define BTFMSLIM_DBG(fmt, arg...) pr_debug("%s: " fmt "\n", __func__, ## arg)
+#define BTFMSLIM_DBG(fmt, arg...) pr_debug(fmt "\n", ## arg)
#define BTFMSLIM_INFO(fmt, arg...) pr_info("%s: " fmt "\n", __func__, ## arg)
#define BTFMSLIM_ERR(fmt, arg...) pr_err("%s: " fmt "\n", __func__, ## arg)
diff --git a/drivers/bluetooth/btfm_slim_codec.c b/drivers/bluetooth/btfm_slim_codec.c
index d7d24ff07801..354b48bfa2a8 100644
--- a/drivers/bluetooth/btfm_slim_codec.c
+++ b/drivers/bluetooth/btfm_slim_codec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, 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
@@ -54,8 +54,8 @@ static int btfm_slim_dai_startup(struct snd_pcm_substream *substream,
int ret;
struct btfmslim *btfmslim = dai->dev->platform_data;
- BTFMSLIM_DBG("substream = %s stream = %d",
- substream->name, substream->stream);
+ BTFMSLIM_DBG("substream = %s stream = %d dai name = %s",
+ substream->name, substream->stream, dai->name);
ret = btfm_slim_hw_init(btfmslim);
return ret;
}
@@ -65,8 +65,8 @@ static void btfm_slim_dai_shutdown(struct snd_pcm_substream *substream,
{
struct btfmslim *btfmslim = dai->dev->platform_data;
- BTFMSLIM_DBG("substream = %s stream = %d",
- substream->name, substream->stream);
+ BTFMSLIM_DBG("substream = %s stream = %d dai name = %s",
+ substream->name, substream->stream, dai->name);
btfm_slim_hw_deinit(btfmslim);
}
@@ -74,7 +74,7 @@ static int btfm_slim_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- BTFMSLIM_DBG("dai_name = %s DAI-ID %x rate %d num_ch %d",
+ BTFMSLIM_DBG("dai name = %s DAI-ID %x rate %d num_ch %d",
dai->name, dai->id, params_rate(params),
params_channels(params));
@@ -89,7 +89,7 @@ int btfm_slim_dai_prepare(struct snd_pcm_substream *substream,
struct btfmslim_ch *ch;
uint8_t rxport, grp = false, nchan = 1;
- BTFMSLIM_DBG("dai->name:%s, dai->id: %d, dai->rate: %d", dai->name,
+ BTFMSLIM_DBG("dai name: %s, dai->id: %d, dai->rate: %d", dai->name,
dai->id, dai->rate);
switch (dai->id) {
@@ -137,7 +137,7 @@ int btfm_slim_dai_hw_free(struct snd_pcm_substream *substream,
struct btfmslim_ch *ch;
uint8_t rxport, grp = false, nchan = 1;
- BTFMSLIM_DBG("dai->name:%s, dai->id: %d, dai->rate: %d", dai->name,
+ BTFMSLIM_DBG("dai name: %s, dai->id: %d, dai->rate: %d", dai->name,
dai->id, dai->rate);
switch (dai->id) {
@@ -384,7 +384,7 @@ static struct snd_soc_dai_driver btfmslim_dai[] = {
static struct snd_soc_codec_driver btfmslim_codec = {
.probe = btfm_slim_codec_probe,
.remove = btfm_slim_codec_remove,
- .read = btfm_slim_codec_read,
+ .read = btfm_slim_codec_read,
.write = btfm_slim_codec_write,
};
diff --git a/drivers/bluetooth/btfm_slim_wcn3990.c b/drivers/bluetooth/btfm_slim_wcn3990.c
index 7d7bd2441c6e..72e28da4bd3b 100644
--- a/drivers/bluetooth/btfm_slim_wcn3990.c
+++ b/drivers/bluetooth/btfm_slim_wcn3990.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, 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
@@ -76,7 +76,7 @@ int btfm_slim_chrk_enable_port(struct btfmslim *btfmslim, uint8_t port_num,
uint8_t reg_val = 0;
uint16_t reg;
- BTFMSLIM_DBG("enable(%d)", enable);
+ BTFMSLIM_DBG("port(%d) enable(%d)", port_num, enable);
if (rxport) {
/* Port enable */
reg = CHRK_SB_PGD_PORT_RX_CFGN(port_num - 0x10);
diff --git a/drivers/clk/msm/clock-generic.c b/drivers/clk/msm/clock-generic.c
index eeb940e434cf..69e47a103402 100644
--- a/drivers/clk/msm/clock-generic.c
+++ b/drivers/clk/msm/clock-generic.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017, 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
@@ -491,6 +491,9 @@ static long __slave_div_round_rate(struct clk *c, unsigned long rate,
if (best_div)
*best_div = div;
+ if (d->data.is_half_divider)
+ p_rate *= 2;
+
return p_rate / div;
}
@@ -530,9 +533,16 @@ static int slave_div_set_rate(struct clk *c, unsigned long rate)
static unsigned long slave_div_get_rate(struct clk *c)
{
struct div_clk *d = to_div_clk(c);
+ unsigned long rate;
+
if (!d->data.div)
return 0;
- return clk_get_rate(c->parent) / d->data.div;
+
+ rate = clk_get_rate(c->parent) / d->data.div;
+ if (d->data.is_half_divider)
+ rate *= 2;
+
+ return rate;
}
struct clk_ops clk_ops_slave_div = {
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index e6054444599c..1d9085cff82c 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -876,5 +876,6 @@ const struct clk_ops clk_alpha_pll_slew_ops = {
.recalc_rate = clk_alpha_pll_recalc_rate,
.round_rate = clk_alpha_pll_round_rate,
.set_rate = clk_alpha_pll_slew_set_rate,
+ .list_registers = clk_alpha_pll_list_registers,
};
EXPORT_SYMBOL_GPL(clk_alpha_pll_slew_ops);
diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c
index 095530e72b78..0d76b6b28985 100644
--- a/drivers/clk/qcom/clk-smd-rpm.c
+++ b/drivers/clk/qcom/clk-smd-rpm.c
@@ -570,8 +570,6 @@ static DEFINE_CLK_VOTER(pnoc_msmbus_clk, pnoc_clk, LONG_MAX);
static DEFINE_CLK_VOTER(pnoc_msmbus_a_clk, pnoc_a_clk, LONG_MAX);
static DEFINE_CLK_VOTER(pnoc_pm_clk, pnoc_clk, LONG_MAX);
static DEFINE_CLK_VOTER(pnoc_sps_clk, pnoc_clk, 0);
-static DEFINE_CLK_VOTER(mmssnoc_a_cpu_clk, mmssnoc_axi_a_clk,
- 19200000);
/* Voter Branch clocks */
static DEFINE_CLK_BRANCH_VOTER(cxo_dwc3_clk, cxo);
@@ -740,7 +738,6 @@ static struct clk_hw *sdm660_clks[] = {
[CXO_PIL_LPASS_CLK] = &cxo_pil_lpass_clk.hw,
[CXO_PIL_CDSP_CLK] = &cxo_pil_cdsp_clk.hw,
[CNOC_PERIPH_KEEPALIVE_A_CLK] = &cnoc_periph_keepalive_a_clk.hw,
- [MMSSNOC_A_CLK_CPU_VOTE] = &mmssnoc_a_cpu_clk.hw
};
static const struct rpm_smd_clk_desc rpm_clk_sdm660 = {
@@ -861,7 +858,6 @@ static int rpm_smd_clk_probe(struct platform_device *pdev)
/* Hold an active set vote for the cnoc_periph resource */
clk_set_rate(cnoc_periph_keepalive_a_clk.hw.clk, 19200000);
clk_prepare_enable(cnoc_periph_keepalive_a_clk.hw.clk);
- clk_prepare_enable(mmssnoc_a_cpu_clk.hw.clk);
}
dev_info(&pdev->dev, "Registered RPM clocks\n");
diff --git a/drivers/clk/qcom/gcc-sdm660.c b/drivers/clk/qcom/gcc-sdm660.c
index 3413859a56ef..c282253da584 100644
--- a/drivers/clk/qcom/gcc-sdm660.c
+++ b/drivers/clk/qcom/gcc-sdm660.c
@@ -730,32 +730,6 @@ static struct clk_rcg2 gp3_clk_src = {
},
};
-static const struct freq_tbl ftbl_hmss_ahb_clk_src[] = {
- F(19200000, P_XO, 1, 0, 0),
- F(37500000, P_GPLL0_OUT_MAIN, 16, 0, 0),
- F(75000000, P_GPLL0_OUT_MAIN, 8, 0, 0),
- F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
- { }
-};
-
-static struct clk_rcg2 hmss_ahb_clk_src = {
- .cmd_rcgr = 0x48014,
- .mnd_width = 0,
- .hid_width = 5,
- .parent_map = gcc_parent_map_1,
- .freq_tbl = ftbl_hmss_ahb_clk_src,
- .clkr.hw.init = &(struct clk_init_data){
- .name = "hmss_ahb_clk_src",
- .parent_names = gcc_parent_names_ao_1,
- .num_parents = 3,
- .ops = &clk_rcg2_ops,
- VDD_DIG_FMAX_MAP3_AO(
- LOWER, 19200000,
- LOW, 50000000,
- NOMINAL, 100000000),
- },
-};
-
static const struct freq_tbl ftbl_hmss_gpll0_clk_src[] = {
F(600000000, P_GPLL0_OUT_MAIN, 1, 0, 0),
{ }
@@ -1823,24 +1797,6 @@ static struct clk_branch gcc_gpu_gpll0_div_clk = {
},
};
-static struct clk_branch gcc_hmss_ahb_clk = {
- .halt_reg = 0x48000,
- .halt_check = BRANCH_HALT_VOTED,
- .clkr = {
- .enable_reg = 0x52004,
- .enable_mask = BIT(21),
- .hw.init = &(struct clk_init_data){
- .name = "gcc_hmss_ahb_clk",
- .parent_names = (const char *[]){
- "hmss_ahb_clk_src",
- },
- .num_parents = 1,
- .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static struct clk_branch gcc_hmss_dvm_bus_clk = {
.halt_reg = 0x4808c,
.halt_check = BRANCH_HALT,
@@ -2493,14 +2449,15 @@ static struct clk_branch gcc_usb3_phy_aux_clk = {
},
};
-static struct clk_gate2 gcc_usb3_phy_pipe_clk = {
- .udelay = 50,
+static struct clk_branch gcc_usb3_phy_pipe_clk = {
+ .halt_reg = 0x50004,
+ .halt_check = BRANCH_HALT_DELAY,
.clkr = {
.enable_reg = 0x50004,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb3_phy_pipe_clk",
- .ops = &clk_gate2_ops,
+ .ops = &clk_branch2_ops,
},
},
};
@@ -2640,7 +2597,6 @@ static struct clk_regmap *gcc_660_clocks[] = {
[GCC_GPU_CFG_AHB_CLK] = &gcc_gpu_cfg_ahb_clk.clkr,
[GCC_GPU_GPLL0_CLK] = &gcc_gpu_gpll0_clk.clkr,
[GCC_GPU_GPLL0_DIV_CLK] = &gcc_gpu_gpll0_div_clk.clkr,
- [GCC_HMSS_AHB_CLK] = &gcc_hmss_ahb_clk.clkr,
[GCC_HMSS_DVM_BUS_CLK] = &gcc_hmss_dvm_bus_clk.clkr,
[GCC_HMSS_RBCPR_CLK] = &gcc_hmss_rbcpr_clk.clkr,
[GCC_MMSS_GPLL0_CLK] = &gcc_mmss_gpll0_clk.clkr,
@@ -2690,7 +2646,6 @@ static struct clk_regmap *gcc_660_clocks[] = {
[GPLL1] = &gpll1_out_main.clkr,
[GPLL4] = &gpll4_out_main.clkr,
[HLOS1_VOTE_LPASS_ADSP_SMMU_CLK] = &hlos1_vote_lpass_adsp_smmu_clk.clkr,
- [HMSS_AHB_CLK_SRC] = &hmss_ahb_clk_src.clkr,
[HMSS_GPLL0_CLK_SRC] = &hmss_gpll0_clk_src.clkr,
[HMSS_GPLL4_CLK_SRC] = &hmss_gpll4_clk_src.clkr,
[HMSS_RBCPR_CLK_SRC] = &hmss_rbcpr_clk_src.clkr,
@@ -2764,12 +2719,6 @@ static int gcc_660_probe(struct platform_device *pdev)
if (IS_ERR(regmap))
return PTR_ERR(regmap);
- /*
- * Set the HMSS_AHB_CLK_SLEEP_ENA bit to allow the hmss_ahb_clk to be
- * turned off by hardware during certain apps low power modes.
- */
- regmap_update_bits(regmap, 0x52008, BIT(21), BIT(21));
-
vdd_dig.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_dig");
if (IS_ERR(vdd_dig.regulator[0])) {
if (!(PTR_ERR(vdd_dig.regulator[0]) == -EPROBE_DEFER))
@@ -2882,7 +2831,6 @@ static const char *const debug_mux_parent_names[] = {
"gcc_gp3_clk",
"gcc_gpu_bimc_gfx_clk",
"gcc_gpu_cfg_ahb_clk",
- "gcc_hmss_ahb_clk",
"gcc_hmss_dvm_bus_clk",
"gcc_hmss_rbcpr_clk",
"gcc_mmss_noc_cfg_ahb_clk",
@@ -3061,7 +3009,6 @@ static struct clk_debug_mux gcc_debug_mux = {
{ "gcc_gp3_clk", 0x0E1 },
{ "gcc_gpu_bimc_gfx_clk", 0x13F },
{ "gcc_gpu_cfg_ahb_clk", 0x13B },
- { "gcc_hmss_ahb_clk", 0x0BA },
{ "gcc_hmss_dvm_bus_clk", 0x0BF },
{ "gcc_hmss_rbcpr_clk", 0x0BC },
{ "gcc_mmss_noc_cfg_ahb_clk", 0x020 },
diff --git a/drivers/clk/qcom/mmcc-sdm660.c b/drivers/clk/qcom/mmcc-sdm660.c
index aec73d62bc18..b908443006af 100644
--- a/drivers/clk/qcom/mmcc-sdm660.c
+++ b/drivers/clk/qcom/mmcc-sdm660.c
@@ -3002,6 +3002,7 @@ static const struct qcom_cc_desc mmcc_660_desc = {
static const struct of_device_id mmcc_660_match_table[] = {
{ .compatible = "qcom,mmcc-sdm660" },
+ { .compatible = "qcom,mmcc-sdm630" },
{ }
};
MODULE_DEVICE_TABLE(of, mmcc_660_match_table);
@@ -3010,11 +3011,15 @@ static int mmcc_660_probe(struct platform_device *pdev)
{
int ret = 0;
struct regmap *regmap;
+ bool is_sdm630 = 0;
regmap = qcom_cc_map(pdev, &mmcc_660_desc);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
+ is_sdm630 = of_device_is_compatible(pdev->dev.of_node,
+ "qcom,mmcc-sdm630");
+
/* PLLs connected on Mx rails of MMSS_CC */
vdd_mx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_mx_mmss");
if (IS_ERR(vdd_mx.regulator[0])) {
@@ -3048,6 +3053,17 @@ static int mmcc_660_probe(struct platform_device *pdev)
clk_alpha_pll_configure(&mmpll8_pll_out_main, regmap, &mmpll8_config);
clk_alpha_pll_configure(&mmpll10_pll_out_main, regmap, &mmpll10_config);
+ if (is_sdm630) {
+ mmcc_660_desc.clks[BYTE1_CLK_SRC] = 0;
+ mmcc_660_desc.clks[MMSS_MDSS_BYTE1_CLK] = 0;
+ mmcc_660_desc.clks[MMSS_MDSS_BYTE1_INTF_DIV_CLK] = 0;
+ mmcc_660_desc.clks[MMSS_MDSS_BYTE1_INTF_CLK] = 0;
+ mmcc_660_desc.clks[ESC1_CLK_SRC] = 0;
+ mmcc_660_desc.clks[MMSS_MDSS_ESC1_CLK] = 0;
+ mmcc_660_desc.clks[PCLK1_CLK_SRC] = 0;
+ mmcc_660_desc.clks[MMSS_MDSS_PCLK1_CLK] = 0;
+ }
+
ret = qcom_cc_really_probe(pdev, &mmcc_660_desc, regmap);
if (ret) {
dev_err(&pdev->dev, "Failed to register MMSS clocks\n");
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 4ca16fc01e1c..442c5d9711a9 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -121,6 +121,7 @@ msm_drm-$(CONFIG_DRM_MSM) += \
msm_gem.o \
msm_gem_prime.o \
msm_gem_submit.o \
+ msm_gem_vma.o \
msm_gpu.o \
msm_iommu.o \
msm_smmu.o \
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index fd266ed963b6..f3a959eedbe0 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -41,7 +41,7 @@ extern bool hang_debug;
static void a3xx_dump(struct msm_gpu *gpu);
-static void a3xx_me_init(struct msm_gpu *gpu)
+static bool a3xx_me_init(struct msm_gpu *gpu)
{
struct msm_ringbuffer *ring = gpu->rb;
@@ -65,7 +65,7 @@ static void a3xx_me_init(struct msm_gpu *gpu)
OUT_RING(ring, 0x00000000);
gpu->funcs->flush(gpu);
- gpu->funcs->idle(gpu);
+ return gpu->funcs->idle(gpu);
}
static int a3xx_hw_init(struct msm_gpu *gpu)
@@ -294,9 +294,7 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
/* clear ME_HALT to start micro engine */
gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0);
- a3xx_me_init(gpu);
-
- return 0;
+ return a3xx_me_init(gpu) ? 0 : -EINVAL;
}
static void a3xx_recover(struct msm_gpu *gpu)
@@ -330,17 +328,22 @@ static void a3xx_destroy(struct msm_gpu *gpu)
kfree(a3xx_gpu);
}
-static void a3xx_idle(struct msm_gpu *gpu)
+static bool a3xx_idle(struct msm_gpu *gpu)
{
/* wait for ringbuffer to drain: */
- adreno_idle(gpu);
+ if (!adreno_idle(gpu))
+ return false;
/* then wait for GPU to finish: */
if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) &
- A3XX_RBBM_STATUS_GPU_BUSY)))
+ A3XX_RBBM_STATUS_GPU_BUSY))) {
DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
- /* TODO maybe we need to reset GPU here to recover from hang? */
+ /* TODO maybe we need to reset GPU here to recover from hang? */
+ return false;
+ }
+
+ return true;
}
static irqreturn_t a3xx_irq(struct msm_gpu *gpu)
@@ -583,7 +586,7 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
#endif
}
- if (!gpu->mmu) {
+ if (!gpu->aspace) {
/* TODO we think it is possible to configure the GPU to
* restrict access to VRAM carveout. But the required
* registers are unknown. For now just bail out and
diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
index 1fa2c7cf34c6..f430b291916d 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
@@ -113,7 +113,7 @@ static void a4xx_enable_hwcg(struct msm_gpu *gpu)
}
-static void a4xx_me_init(struct msm_gpu *gpu)
+static bool a4xx_me_init(struct msm_gpu *gpu)
{
struct msm_ringbuffer *ring = gpu->rb;
@@ -137,7 +137,7 @@ static void a4xx_me_init(struct msm_gpu *gpu)
OUT_RING(ring, 0x00000000);
gpu->funcs->flush(gpu);
- gpu->funcs->idle(gpu);
+ return gpu->funcs->idle(gpu);
}
static int a4xx_hw_init(struct msm_gpu *gpu)
@@ -292,9 +292,7 @@ static int a4xx_hw_init(struct msm_gpu *gpu)
/* clear ME_HALT to start micro engine */
gpu_write(gpu, REG_A4XX_CP_ME_CNTL, 0);
- a4xx_me_init(gpu);
-
- return 0;
+ return a4xx_me_init(gpu) ? 0 : -EINVAL;
}
static void a4xx_recover(struct msm_gpu *gpu)
@@ -328,17 +326,21 @@ static void a4xx_destroy(struct msm_gpu *gpu)
kfree(a4xx_gpu);
}
-static void a4xx_idle(struct msm_gpu *gpu)
+static bool a4xx_idle(struct msm_gpu *gpu)
{
/* wait for ringbuffer to drain: */
- adreno_idle(gpu);
+ if (!adreno_idle(gpu))
+ return false;
/* then wait for GPU to finish: */
if (spin_until(!(gpu_read(gpu, REG_A4XX_RBBM_STATUS) &
- A4XX_RBBM_STATUS_GPU_BUSY)))
+ A4XX_RBBM_STATUS_GPU_BUSY))) {
DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
+ /* TODO maybe we need to reset GPU here to recover from hang? */
+ return false;
+ }
- /* TODO maybe we need to reset GPU here to recover from hang? */
+ return true;
}
static irqreturn_t a4xx_irq(struct msm_gpu *gpu)
@@ -665,7 +667,7 @@ struct msm_gpu *a4xx_gpu_init(struct drm_device *dev)
#endif
}
- if (!gpu->mmu) {
+ if (!gpu->aspace) {
/* TODO we think it is possible to configure the GPU to
* restrict access to VRAM carveout. But the required
* registers are unknown. For now just bail out and
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 4951172ede06..4b518bfdeee4 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -227,19 +227,18 @@ void adreno_flush(struct msm_gpu *gpu)
adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_WPTR, wptr);
}
-void adreno_idle(struct msm_gpu *gpu)
+bool adreno_idle(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
uint32_t wptr = get_wptr(gpu->rb);
- int ret;
/* wait for CP to drain ringbuffer: */
- ret = spin_until(get_rptr(adreno_gpu) == wptr);
-
- if (ret)
- DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);
+ if (!spin_until(get_rptr(adreno_gpu) == wptr))
+ return true;
/* TODO maybe we need to reset GPU here to recover from hang? */
+ DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);
+ return false;
}
#ifdef CONFIG_DEBUG_FS
@@ -390,7 +389,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
return ret;
}
- mmu = gpu->mmu;
+ mmu = gpu->aspace->mmu;
if (mmu) {
ret = mmu->funcs->attach(mmu, iommu_ports,
ARRAY_SIZE(iommu_ports));
@@ -427,6 +426,8 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
void adreno_gpu_cleanup(struct adreno_gpu *gpu)
{
+ struct msm_gem_address_space *aspace = gpu->base.aspace;
+
if (gpu->memptrs_bo) {
if (gpu->memptrs_iova)
msm_gem_put_iova(gpu->memptrs_bo, gpu->base.id);
@@ -434,5 +435,12 @@ void adreno_gpu_cleanup(struct adreno_gpu *gpu)
}
release_firmware(gpu->pm4);
release_firmware(gpu->pfp);
+
msm_gpu_cleanup(&gpu->base);
+
+ if (aspace) {
+ aspace->mmu->funcs->detach(aspace->mmu,
+ iommu_ports, ARRAY_SIZE(iommu_ports));
+ msm_gem_address_space_destroy(aspace);
+ }
}
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 1d07511f4d22..aea39d357dc0 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -241,7 +241,7 @@ void adreno_recover(struct msm_gpu *gpu);
int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
struct msm_file_private *ctx);
void adreno_flush(struct msm_gpu *gpu);
-void adreno_idle(struct msm_gpu *gpu);
+bool adreno_idle(struct msm_gpu *gpu);
#ifdef CONFIG_DEBUG_FS
void adreno_show(struct msm_gpu *gpu, struct seq_file *m);
#endif
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index f0f66ac4b2fb..6d8e174236ea 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
@@ -17,6 +17,7 @@
#include "msm_drv.h"
+#include "msm_gem.h"
#include "msm_mmu.h"
#include "mdp4_kms.h"
@@ -177,18 +178,35 @@ static void mdp4_preclose(struct msm_kms *kms, struct drm_file *file)
struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
struct msm_drm_private *priv = mdp4_kms->dev->dev_private;
unsigned i;
+ struct msm_gem_address_space *aspace = mdp4_kms->aspace;
for (i = 0; i < priv->num_crtcs; i++)
mdp4_crtc_cancel_pending_flip(priv->crtcs[i], file);
+
+ if (aspace) {
+ aspace->mmu->funcs->detach(aspace->mmu,
+ iommu_ports, ARRAY_SIZE(iommu_ports));
+ msm_gem_address_space_destroy(aspace);
+ }
}
static void mdp4_destroy(struct msm_kms *kms)
{
+ struct device *dev = mdp4_kms->dev->dev;
+ struct msm_gem_address_space *aspace = mdp4_kms->aspace;
+
struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
if (mdp4_kms->blank_cursor_iova)
msm_gem_put_iova(mdp4_kms->blank_cursor_bo, mdp4_kms->id);
if (mdp4_kms->blank_cursor_bo)
drm_gem_object_unreference_unlocked(mdp4_kms->blank_cursor_bo);
+
+ if (aspace) {
+ aspace->mmu->funcs->detach(aspace->mmu,
+ iommu_ports, ARRAY_SIZE(iommu_ports));
+ msm_gem_address_space_destroy(aspace);
+ }
+
kfree(mdp4_kms);
}
@@ -408,7 +426,7 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
struct mdp4_platform_config *config = mdp4_get_config(pdev);
struct mdp4_kms *mdp4_kms;
struct msm_kms *kms = NULL;
- struct msm_mmu *mmu;
+ struct msm_gem_address_space *aspace;
int ret;
mdp4_kms = kzalloc(sizeof(*mdp4_kms), GFP_KERNEL);
@@ -497,22 +515,33 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
mdelay(16);
if (config->iommu) {
- mmu = msm_iommu_new(&pdev->dev, config->iommu);
+ struct msm_mmu *mmu = msm_iommu_new(&pdev->dev, config->iommu);
+
if (IS_ERR(mmu)) {
ret = PTR_ERR(mmu);
goto fail;
}
- ret = mmu->funcs->attach(mmu, iommu_ports,
+
+ aspace = msm_gem_address_space_create(&pdev->dev,
+ mmu, "mdp4", 0x1000, 0xffffffff);
+ if (IS_ERR(aspace)) {
+ ret = PTR_ERR(aspace);
+ goto fail;
+ }
+
+ mdp4_kms->aspace = aspace;
+
+ ret = aspace->mmu->funcs->attach(aspace->mmu, iommu_ports,
ARRAY_SIZE(iommu_ports));
if (ret)
goto fail;
} else {
dev_info(dev->dev, "no iommu, fallback to phys "
"contig buffers for scanout\n");
- mmu = NULL;
+ aspace = NULL;
}
- mdp4_kms->id = msm_register_mmu(dev, mmu);
+ mdp4_kms->id = msm_register_address_space(dev, aspace);
if (mdp4_kms->id < 0) {
ret = mdp4_kms->id;
dev_err(dev->dev, "failed to register mdp4 iommu: %d\n", ret);
@@ -562,6 +591,7 @@ static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev)
/* TODO */
config.max_clk = 266667000;
config.iommu = iommu_domain_alloc(msm_iommu_get_bus(&dev->dev));
+
#else
if (cpu_is_apq8064())
config.max_clk = 266667000;
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
index 8a7f6e1e2bca..923a028db452 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
@@ -45,6 +45,7 @@ struct mdp4_kms {
struct clk *pclk;
struct clk *lut_clk;
struct clk *axi_clk;
+ struct msm_gem_address_space *aspace;
struct mdp_irq error_handler;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index f7aebf5516ce..cc5a73505537 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016-2017 The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -18,6 +18,7 @@
#include "msm_drv.h"
+#include "msm_gem.h"
#include "msm_mmu.h"
#include "mdp5_kms.h"
@@ -130,13 +131,14 @@ static void mdp5_preclose(struct msm_kms *kms, struct drm_file *file)
static void mdp5_destroy(struct msm_kms *kms)
{
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
- struct msm_mmu *mmu = mdp5_kms->mmu;
+ struct msm_gem_address_space *aspace = mdp5_kms->aspace;
mdp5_irq_domain_fini(mdp5_kms);
- if (mmu) {
- mmu->funcs->detach(mmu, iommu_ports, ARRAY_SIZE(iommu_ports));
- mmu->funcs->destroy(mmu);
+ if (aspace) {
+ aspace->mmu->funcs->detach(aspace->mmu,
+ iommu_ports, ARRAY_SIZE(iommu_ports));
+ msm_gem_address_space_destroy(aspace);
}
if (mdp5_kms->ctlm)
@@ -474,7 +476,7 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
struct mdp5_cfg *config;
struct mdp5_kms *mdp5_kms;
struct msm_kms *kms = NULL;
- struct msm_mmu *mmu;
+ struct msm_gem_address_space *aspace;
uint32_t major, minor;
int i, ret;
@@ -595,30 +597,37 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
mdelay(16);
if (config->platform.iommu) {
- mmu = msm_smmu_new(&pdev->dev,
+ struct msm_mmu *mmu = msm_smmu_new(&pdev->dev,
MSM_SMMU_DOMAIN_UNSECURE);
if (IS_ERR(mmu)) {
ret = PTR_ERR(mmu);
dev_err(dev->dev, "failed to init iommu: %d\n", ret);
iommu_domain_free(config->platform.iommu);
+ }
+
+ aspace = msm_gem_smmu_address_space_create(&pdev->dev,
+ mmu, "mdp5");
+ if (IS_ERR(aspace)) {
+ ret = PTR_ERR(aspace);
goto fail;
}
- ret = mmu->funcs->attach(mmu, iommu_ports,
+ mdp5_kms->aspace = aspace;
+
+ ret = aspace->mmu->funcs->attach(aspace->mmu, iommu_ports,
ARRAY_SIZE(iommu_ports));
if (ret) {
- dev_err(dev->dev, "failed to attach iommu: %d\n", ret);
- mmu->funcs->destroy(mmu);
+ dev_err(&pdev->dev, "failed to attach iommu: %d\n",
+ ret);
goto fail;
}
} else {
- dev_info(dev->dev, "no iommu, fallback to phys "
- "contig buffers for scanout\n");
- mmu = NULL;
+ dev_info(&pdev->dev,
+ "no iommu, fallback to phys contig buffers for scanout\n");
+ aspace = NULL;
}
- mdp5_kms->mmu = mmu;
- mdp5_kms->id = msm_register_mmu(dev, mmu);
+ mdp5_kms->id = msm_register_address_space(dev, aspace);
if (mdp5_kms->id < 0) {
ret = mdp5_kms->id;
dev_err(dev->dev, "failed to register mdp5 iommu: %d\n", ret);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index 84f65d415598..6cb43ad0c1d7 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -37,7 +37,7 @@ struct mdp5_kms {
/* mapper-id used to request GEM buffer mapped for scanout: */
int id;
- struct msm_mmu *mmu;
+ struct msm_gem_address_space *aspace;
struct mdp5_smp *smp;
struct mdp5_ctl_manager *ctlm;
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 1dcf88a23afa..4b67edf5a77b 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -38,42 +38,20 @@ static const struct drm_mode_config_funcs mode_config_funcs = {
.atomic_commit = msm_atomic_commit,
};
-int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu)
+int msm_register_address_space(struct drm_device *dev,
+ struct msm_gem_address_space *aspace)
{
struct msm_drm_private *priv = dev->dev_private;
- int idx = priv->num_mmus++;
+ int idx = priv->num_aspaces++;
- if (WARN_ON(idx >= ARRAY_SIZE(priv->mmus)))
+ if (WARN_ON(idx >= ARRAY_SIZE(priv->aspace)))
return -EINVAL;
- priv->mmus[idx] = mmu;
+ priv->aspace[idx] = aspace;
return idx;
}
-void msm_unregister_mmu(struct drm_device *dev, struct msm_mmu *mmu)
-{
- struct msm_drm_private *priv = dev->dev_private;
- int idx;
-
- if (priv->num_mmus <= 0) {
- dev_err(dev->dev, "invalid num mmus %d\n", priv->num_mmus);
- return;
- }
-
- idx = priv->num_mmus - 1;
-
- /* only support reverse-order deallocation */
- if (priv->mmus[idx] != mmu) {
- dev_err(dev->dev, "unexpected mmu at idx %d\n", idx);
- return;
- }
-
- --priv->num_mmus;
- priv->mmus[idx] = 0;
-}
-
-
#ifdef CONFIG_DRM_MSM_REGISTER_LOGGING
static bool reglog = false;
MODULE_PARM_DESC(reglog, "Enable register read/write logging");
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index a2678882d57a..4ed5953d07f9 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -63,6 +63,8 @@ struct msm_mmu;
struct msm_rd_state;
struct msm_perf_state;
struct msm_gem_submit;
+struct msm_gem_address_space;
+struct msm_gem_vma;
#define NUM_DOMAINS 4 /* one for KMS, then one per gpu core (?) */
#define MAX_CRTCS 8
@@ -296,9 +298,13 @@ struct msm_drm_private {
uint32_t pending_crtcs;
wait_queue_head_t pending_crtcs_event;
- /* registered MMUs: */
- unsigned int num_mmus;
- struct msm_mmu *mmus[NUM_DOMAINS];
+ /* Registered address spaces.. currently this is fixed per # of
+ * iommu's. Ie. one for display block and one for gpu block.
+ * Eventually, to do per-process gpu pagetables, we'll want one
+ * of these per-process.
+ */
+ unsigned int num_aspaces;
+ struct msm_gem_address_space *aspace[NUM_DOMAINS];
unsigned int num_planes;
struct drm_plane *planes[MAX_PLANES];
@@ -362,15 +368,32 @@ void __msm_fence_worker(struct work_struct *work);
int msm_atomic_commit(struct drm_device *dev,
struct drm_atomic_state *state, bool async);
-int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
-void msm_unregister_mmu(struct drm_device *dev, struct msm_mmu *mmu);
-
int msm_wait_fence(struct drm_device *dev, uint32_t fence,
ktime_t *timeout, bool interruptible);
int msm_queue_fence_cb(struct drm_device *dev,
struct msm_fence_cb *cb, uint32_t fence);
void msm_update_fence(struct drm_device *dev, uint32_t fence);
+int msm_register_address_space(struct drm_device *dev,
+ struct msm_gem_address_space *aspace);
+void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
+ struct msm_gem_vma *vma, struct sg_table *sgt,
+ void *priv);
+int msm_gem_map_vma(struct msm_gem_address_space *aspace,
+ struct msm_gem_vma *vma, struct sg_table *sgt,
+ void *priv);
+void msm_gem_address_space_destroy(struct msm_gem_address_space *aspace);
+
+/* For GPU and legacy display */
+struct msm_gem_address_space *
+msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain,
+ const char *name);
+
+/* For SDE display */
+struct msm_gem_address_space *
+msm_gem_smmu_address_space_create(struct device *dev, struct msm_mmu *mmu,
+ const char *name);
+
int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
struct drm_file *file);
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 4e69fba410c3..5aa08cf4d6d8 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -24,6 +24,11 @@
#include "msm_gpu.h"
#include "msm_mmu.h"
+static void *get_dmabuf_ptr(struct drm_gem_object *obj)
+{
+ return (obj && obj->import_attach) ? obj->import_attach->dmabuf : NULL;
+}
+
static dma_addr_t physaddr(struct drm_gem_object *obj)
{
struct msm_gem_object *msm_obj = to_msm_bo(obj);
@@ -279,21 +284,8 @@ put_iova(struct drm_gem_object *obj)
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
for (id = 0; id < ARRAY_SIZE(msm_obj->domain); id++) {
- struct msm_mmu *mmu = priv->mmus[id];
-
- if (!mmu || !msm_obj->domain[id].iova)
- continue;
-
- if (obj->import_attach) {
- if (mmu->funcs->unmap_dma_buf)
- mmu->funcs->unmap_dma_buf(mmu, msm_obj->sgt,
- obj->import_attach->dmabuf,
- DMA_BIDIRECTIONAL);
- } else
- mmu->funcs->unmap_sg(mmu, msm_obj->sgt,
- DMA_BIDIRECTIONAL);
-
- msm_obj->domain[id].iova = 0;
+ msm_gem_unmap_vma(priv->aspace[id], &msm_obj->domain[id],
+ msm_obj->sgt, get_dmabuf_ptr(obj));
}
}
@@ -318,31 +310,11 @@ int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id,
return PTR_ERR(pages);
if (iommu_present(&platform_bus_type)) {
- struct msm_mmu *mmu = priv->mmus[id];
-
- if (WARN_ON(!mmu))
- return -EINVAL;
-
- if (obj->import_attach && mmu->funcs->map_dma_buf) {
- ret = mmu->funcs->map_dma_buf(mmu, msm_obj->sgt,
- obj->import_attach->dmabuf,
- DMA_BIDIRECTIONAL);
- if (ret) {
- DRM_ERROR("Unable to map dma buf\n");
- return ret;
- }
- } else {
- ret = mmu->funcs->map_sg(mmu, msm_obj->sgt,
- DMA_BIDIRECTIONAL);
- }
-
- if (!ret)
- msm_obj->domain[id].iova =
- sg_dma_address(msm_obj->sgt->sgl);
- } else {
- WARN_ONCE(1, "physical address being used\n");
+ ret = msm_gem_map_vma(priv->aspace[id],
+ &msm_obj->domain[id], msm_obj->sgt,
+ get_dmabuf_ptr(obj));
+ } else
msm_obj->domain[id].iova = physaddr(obj);
- }
}
if (!ret)
@@ -515,14 +487,21 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
{
struct drm_device *dev = obj->dev;
struct msm_gem_object *msm_obj = to_msm_bo(obj);
+ struct msm_drm_private *priv = obj->dev->dev_private;
uint64_t off = drm_vma_node_start(&obj->vma_node);
+ int id;
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
- seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p %zu\n",
+ seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p\t",
msm_obj->flags, is_active(msm_obj) ? 'A' : 'I',
msm_obj->read_fence, msm_obj->write_fence,
obj->name, obj->refcount.refcount.counter,
- off, msm_obj->vaddr, obj->size);
+ off, msm_obj->vaddr);
+
+ for (id = 0; id < priv->num_aspaces; id++)
+ seq_printf(m, " %08llx", msm_obj->domain[id].iova);
+
+ seq_puts(m, "\n");
}
void msm_gem_describe_objects(struct list_head *list, struct seq_file *m)
@@ -559,7 +538,8 @@ void msm_gem_free_object(struct drm_gem_object *obj)
if (obj->import_attach) {
if (msm_obj->vaddr)
- dma_buf_vunmap(obj->import_attach->dmabuf, msm_obj->vaddr);
+ dma_buf_vunmap(obj->import_attach->dmabuf,
+ msm_obj->vaddr);
/* Don't drop the pages for imported dmabuf, as they are not
* ours, just free the array we allocated:
@@ -613,7 +593,6 @@ static int msm_gem_new_impl(struct drm_device *dev,
{
struct msm_drm_private *priv = dev->dev_private;
struct msm_gem_object *msm_obj;
- unsigned sz;
bool use_vram = false;
switch (flags & MSM_BO_CACHE_MASK) {
@@ -635,16 +614,12 @@ static int msm_gem_new_impl(struct drm_device *dev,
if (WARN_ON(use_vram && !priv->vram.size))
return -EINVAL;
- sz = sizeof(*msm_obj);
- if (use_vram)
- sz += sizeof(struct drm_mm_node);
-
- msm_obj = kzalloc(sz, GFP_KERNEL);
+ msm_obj = kzalloc(sizeof(*msm_obj), GFP_KERNEL);
if (!msm_obj)
return -ENOMEM;
if (use_vram)
- msm_obj->vram_node = (void *)&msm_obj[1];
+ msm_obj->vram_node = &msm_obj->domain[0].node;
msm_obj->flags = flags;
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index 2e4ae6b1c5d0..86c297c6de32 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -24,6 +24,28 @@
/* Additional internal-use only BO flags: */
#define MSM_BO_STOLEN 0x10000000 /* try to use stolen/splash memory */
+struct msm_gem_aspace_ops {
+ int (*map)(struct msm_gem_address_space *, struct msm_gem_vma *,
+ struct sg_table *sgt, void *priv);
+
+ void (*unmap)(struct msm_gem_address_space *, struct msm_gem_vma *,
+ struct sg_table *sgt, void *priv);
+
+ void (*destroy)(struct msm_gem_address_space *);
+};
+
+struct msm_gem_address_space {
+ const char *name;
+ struct msm_mmu *mmu;
+ const struct msm_gem_aspace_ops *ops;
+};
+
+struct msm_gem_vma {
+ /* Node used by the GPU address space, but not the SDE address space */
+ struct drm_mm_node node;
+ uint64_t iova;
+};
+
struct msm_gem_object {
struct drm_gem_object base;
@@ -52,9 +74,7 @@ struct msm_gem_object {
struct sg_table *sgt;
void *vaddr;
- struct {
- dma_addr_t iova;
- } domain[NUM_DOMAINS];
+ struct msm_gem_vma domain[NUM_DOMAINS];
/* normally (resv == &_resv) except for imported bo's */
struct reservation_object *resv;
diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c
new file mode 100644
index 000000000000..53e70263e03c
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_gem_vma.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2016 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "msm_drv.h"
+#include "msm_gem.h"
+#include "msm_mmu.h"
+
+/* SDE address space operations */
+static void smmu_aspace_unmap_vma(struct msm_gem_address_space *aspace,
+ struct msm_gem_vma *vma, struct sg_table *sgt,
+ void *priv)
+{
+ struct dma_buf *buf = priv;
+
+ if (buf)
+ aspace->mmu->funcs->unmap_dma_buf(aspace->mmu,
+ sgt, buf, DMA_BIDIRECTIONAL);
+ else
+ aspace->mmu->funcs->unmap_sg(aspace->mmu, sgt,
+ DMA_BIDIRECTIONAL);
+
+ vma->iova = 0;
+}
+
+
+static int smmu_aspace_map_vma(struct msm_gem_address_space *aspace,
+ struct msm_gem_vma *vma, struct sg_table *sgt,
+ void *priv)
+{
+ struct dma_buf *buf = priv;
+ int ret;
+
+ if (buf)
+ ret = aspace->mmu->funcs->map_dma_buf(aspace->mmu, sgt, buf,
+ DMA_BIDIRECTIONAL);
+ else
+ ret = aspace->mmu->funcs->map_sg(aspace->mmu, sgt,
+ DMA_BIDIRECTIONAL);
+
+ if (!ret)
+ vma->iova = sg_dma_address(sgt->sgl);
+
+ return ret;
+}
+
+static const struct msm_gem_aspace_ops smmu_aspace_ops = {
+ .map = smmu_aspace_map_vma,
+ .unmap = smmu_aspace_unmap_vma,
+};
+
+struct msm_gem_address_space *
+msm_gem_smmu_address_space_create(struct device *dev, struct msm_mmu *mmu,
+ const char *name)
+{
+ struct msm_gem_address_space *aspace;
+
+ if (!mmu)
+ return ERR_PTR(-EINVAL);
+
+ aspace = kzalloc(sizeof(*aspace), GFP_KERNEL);
+ if (!aspace)
+ return ERR_PTR(-ENOMEM);
+
+ aspace->name = name;
+ aspace->mmu = mmu;
+ aspace->ops = &smmu_aspace_ops;
+
+ return aspace;
+}
+
+/* GPU address space operations */
+struct msm_iommu_aspace {
+ struct msm_gem_address_space base;
+ struct drm_mm mm;
+};
+
+#define to_iommu_aspace(aspace) \
+ ((struct msm_iommu_aspace *) \
+ container_of(aspace, struct msm_iommu_aspace, base))
+
+static void iommu_aspace_unmap_vma(struct msm_gem_address_space *aspace,
+ struct msm_gem_vma *vma, struct sg_table *sgt, void *priv)
+{
+ if (!vma->iova)
+ return;
+
+ if (aspace->mmu)
+ aspace->mmu->funcs->unmap(aspace->mmu, vma->iova, sgt);
+
+ drm_mm_remove_node(&vma->node);
+
+ vma->iova = 0;
+}
+
+static int iommu_aspace_map_vma(struct msm_gem_address_space *aspace,
+ struct msm_gem_vma *vma, struct sg_table *sgt,
+ void *priv)
+{
+ struct msm_iommu_aspace *local = to_iommu_aspace(aspace);
+ size_t size = 0;
+ struct scatterlist *sg;
+ int ret = 0, i;
+
+ if (WARN_ON(drm_mm_node_allocated(&vma->node)))
+ return 0;
+
+ for_each_sg(sgt->sgl, sg, sgt->nents, i)
+ size += sg->length + sg->offset;
+
+ ret = drm_mm_insert_node(&local->mm, &vma->node, size >> PAGE_SHIFT,
+ 0, DRM_MM_SEARCH_DEFAULT);
+ if (ret)
+ return ret;
+
+ vma->iova = vma->node.start << PAGE_SHIFT;
+
+ if (aspace->mmu)
+ ret = aspace->mmu->funcs->map(aspace->mmu, vma->iova,
+ sgt, IOMMU_READ | IOMMU_WRITE);
+
+ return ret;
+}
+
+static void iommu_aspace_destroy(struct msm_gem_address_space *aspace)
+{
+ struct msm_iommu_aspace *local = to_iommu_aspace(aspace);
+
+ drm_mm_takedown(&local->mm);
+ aspace->mmu->funcs->destroy(aspace->mmu);
+}
+
+static const struct msm_gem_aspace_ops msm_iommu_aspace_ops = {
+ .map = iommu_aspace_map_vma,
+ .unmap = iommu_aspace_unmap_vma,
+ .destroy = iommu_aspace_destroy,
+};
+
+static struct msm_gem_address_space *
+msm_gem_address_space_new(struct msm_mmu *mmu, const char *name,
+ uint64_t start, uint64_t end)
+{
+ struct msm_iommu_aspace *local;
+
+ if (!mmu)
+ return ERR_PTR(-EINVAL);
+
+ local = kzalloc(sizeof(*local), GFP_KERNEL);
+ if (!local)
+ return ERR_PTR(-ENOMEM);
+
+ drm_mm_init(&local->mm, (start >> PAGE_SHIFT),
+ (end >> PAGE_SHIFT) - 1);
+
+ local->base.name = name;
+ local->base.mmu = mmu;
+ local->base.ops = &msm_iommu_aspace_ops;
+
+ return &local->base;
+}
+
+int msm_gem_map_vma(struct msm_gem_address_space *aspace,
+ struct msm_gem_vma *vma, struct sg_table *sgt,
+ void *priv)
+{
+ if (aspace && aspace->ops->map)
+ return aspace->ops->map(aspace, vma, sgt, priv);
+
+ return -EINVAL;
+}
+
+void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
+ struct msm_gem_vma *vma, struct sg_table *sgt, void *priv)
+{
+ if (aspace && aspace->ops->unmap)
+ aspace->ops->unmap(aspace, vma, sgt, priv);
+}
+
+struct msm_gem_address_space *
+msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain,
+ const char *name)
+{
+ struct msm_mmu *mmu = msm_iommu_new(dev, domain);
+
+ if (IS_ERR(mmu))
+ return (struct msm_gem_address_space *) mmu;
+
+ return msm_gem_address_space_new(mmu, name,
+ domain->geometry.aperture_start,
+ domain->geometry.aperture_end);
+}
+
+void
+msm_gem_address_space_destroy(struct msm_gem_address_space *aspace)
+{
+ if (aspace && aspace->ops->destroy)
+ aspace->ops->destroy(aspace);
+
+ kfree(aspace);
+}
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 6b02ada6579a..7b8f2d02b56d 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -649,12 +649,17 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
*/
iommu = iommu_domain_alloc(&platform_bus_type);
if (iommu) {
+ /* TODO 32b vs 64b address space.. */
+ iommu->geometry.aperture_start = 0x1000;
+ iommu->geometry.aperture_end = 0xffffffff;
+
dev_info(drm->dev, "%s: using IOMMU\n", name);
- gpu->mmu = msm_iommu_new(&pdev->dev, iommu);
- if (IS_ERR(gpu->mmu)) {
- ret = PTR_ERR(gpu->mmu);
+ gpu->aspace = msm_gem_address_space_create(&pdev->dev,
+ iommu, "gpu");
+ if (IS_ERR(gpu->aspace)) {
+ ret = PTR_ERR(gpu->aspace);
dev_err(drm->dev, "failed to init iommu: %d\n", ret);
- gpu->mmu = NULL;
+ gpu->aspace = NULL;
iommu_domain_free(iommu);
goto fail;
}
@@ -662,7 +667,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
} else {
dev_info(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name);
}
- gpu->id = msm_register_mmu(drm, gpu->mmu);
+ gpu->id = msm_register_address_space(drm, gpu->aspace);
/* Create ringbuffer: */
@@ -697,7 +702,4 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
msm_gem_put_iova(gpu->rb->bo, gpu->id);
msm_ringbuffer_destroy(gpu->rb);
}
-
- if (gpu->mmu)
- gpu->mmu->funcs->destroy(gpu->mmu);
}
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 2bbe85a3d6f6..309422b73a49 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -49,7 +49,7 @@ struct msm_gpu_funcs {
int (*submit)(struct msm_gpu *gpu, struct msm_gem_submit *submit,
struct msm_file_private *ctx);
void (*flush)(struct msm_gpu *gpu);
- void (*idle)(struct msm_gpu *gpu);
+ bool (*idle)(struct msm_gpu *gpu);
irqreturn_t (*irq)(struct msm_gpu *irq);
uint32_t (*last_fence)(struct msm_gpu *gpu);
void (*recover)(struct msm_gpu *gpu);
@@ -95,7 +95,7 @@ struct msm_gpu {
void __iomem *mmio;
int irq;
- struct msm_mmu *mmu;
+ struct msm_gem_address_space *aspace;
int id;
/* Power Control: */
diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
index c8c7755c8370..3d750eca5cae 100644
--- a/drivers/gpu/drm/msm/msm_mmu.h
+++ b/drivers/gpu/drm/msm/msm_mmu.h
@@ -21,7 +21,6 @@
#include <linux/iommu.h>
struct msm_mmu;
-struct msm_gpu;
enum msm_mmu_domain_type {
MSM_SMMU_DOMAIN_UNSECURE,
@@ -61,7 +60,6 @@ static inline void msm_mmu_init(struct msm_mmu *mmu, struct device *dev,
}
struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain);
-struct msm_mmu *msm_gpummu_new(struct device *dev, struct msm_gpu *gpu);
struct msm_mmu *msm_smmu_new(struct device *dev,
enum msm_mmu_domain_type domain);
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index afe90d16e31d..e40e33f11fd9 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -941,15 +941,15 @@ static int _sde_kms_mmu_destroy(struct sde_kms *sde_kms)
int i;
for (i = ARRAY_SIZE(sde_kms->mmu_id) - 1; i >= 0; i--) {
- if (!sde_kms->mmu[i])
+ mmu = sde_kms->aspace[i]->mmu;
+
+ if (!mmu)
continue;
- mmu = sde_kms->mmu[i];
- msm_unregister_mmu(sde_kms->dev, mmu);
mmu->funcs->detach(mmu, (const char **)iommu_ports,
ARRAY_SIZE(iommu_ports));
- mmu->funcs->destroy(mmu);
- sde_kms->mmu[i] = 0;
+ msm_gem_address_space_destroy(sde_kms->aspace[i]);
+
sde_kms->mmu_id[i] = 0;
}
@@ -962,6 +962,8 @@ static int _sde_kms_mmu_init(struct sde_kms *sde_kms)
int i, ret;
for (i = 0; i < MSM_SMMU_DOMAIN_MAX; i++) {
+ struct msm_gem_address_space *aspace;
+
mmu = msm_smmu_new(sde_kms->dev->dev, i);
if (IS_ERR(mmu)) {
/* MMU's can be optional depending on platform */
@@ -971,25 +973,35 @@ static int _sde_kms_mmu_init(struct sde_kms *sde_kms)
continue;
}
+ aspace = msm_gem_smmu_address_space_create(sde_kms->dev->dev,
+ mmu, "sde");
+ if (IS_ERR(aspace)) {
+ ret = PTR_ERR(aspace);
+ mmu->funcs->destroy(mmu);
+ goto fail;
+ }
+
+ sde_kms->aspace[i] = aspace;
+
ret = mmu->funcs->attach(mmu, (const char **)iommu_ports,
ARRAY_SIZE(iommu_ports));
if (ret) {
SDE_ERROR("failed to attach iommu %d: %d\n", i, ret);
- mmu->funcs->destroy(mmu);
+ msm_gem_address_space_destroy(aspace);
goto fail;
}
- sde_kms->mmu_id[i] = msm_register_mmu(sde_kms->dev, mmu);
+ sde_kms->mmu_id[i] = msm_register_address_space(sde_kms->dev,
+ aspace);
if (sde_kms->mmu_id[i] < 0) {
ret = sde_kms->mmu_id[i];
SDE_ERROR("failed to register sde iommu %d: %d\n",
i, ret);
mmu->funcs->detach(mmu, (const char **)iommu_ports,
ARRAY_SIZE(iommu_ports));
+ msm_gem_address_space_destroy(aspace);
goto fail;
}
-
- sde_kms->mmu[i] = mmu;
}
return 0;
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index bf127ffe9eb6..8663c632699b 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -22,6 +22,7 @@
#include "msm_drv.h"
#include "msm_kms.h"
#include "msm_mmu.h"
+#include "msm_gem.h"
#include "sde_dbg.h"
#include "sde_hw_catalog.h"
#include "sde_hw_ctl.h"
@@ -121,7 +122,7 @@ struct sde_kms {
int core_rev;
struct sde_mdss_cfg *catalog;
- struct msm_mmu *mmu[MSM_SMMU_DOMAIN_MAX];
+ struct msm_gem_address_space *aspace[MSM_SMMU_DOMAIN_MAX];
int mmu_id[MSM_SMMU_DOMAIN_MAX];
struct sde_power_client *core_client;
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index 0d068e9c5805..89218b62bb7d 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, 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
@@ -2327,10 +2327,6 @@ static int adreno_dispatch_process_drawqueue(struct adreno_device *adreno_dev,
if (adreno_drawqueue_is_empty(drawqueue))
return count;
- /* Don't update the drawqueue timeout if we are about to preempt out */
- if (!adreno_in_preempt_state(adreno_dev, ADRENO_PREEMPT_NONE))
- return count;
-
/* Don't update the drawqueue timeout if it isn't active */
if (!drawqueue_is_current(drawqueue))
return count;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 2b227f2c3a6c..601e7a23101b 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -4379,8 +4379,9 @@ kgsl_get_unmapped_area(struct file *file, unsigned long addr,
val = _get_svm_area(private, entry, addr, len, flags);
if (IS_ERR_VALUE(val))
KGSL_MEM_ERR(device,
- "_get_svm_area: pid %d addr %lx pgoff %lx len %ld failed error %d\n",
- private->pid, addr, pgoff, len, (int) val);
+ "_get_svm_area: pid %d mmap_base %lx addr %lx pgoff %lx len %ld failed error %d\n",
+ private->pid, current->mm->mmap_base, addr,
+ pgoff, len, (int) val);
}
put:
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index f13017cd9d46..99de4002275e 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1128,17 +1128,6 @@ config TOUCHSCREEN_FT5X06_GESTURE
If unsure, say N.
-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 7606fe53fcff..a32132cffe92 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -98,6 +98,5 @@ 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
obj-$(CONFIG_TOUCHSCREEN_GT9XX) += gt9xx/
obj-$(CONFIG_TOUCHSCREEN_ST) += st/
diff --git a/drivers/input/touchscreen/msg21xx_ts.c b/drivers/input/touchscreen/msg21xx_ts.c
deleted file mode 100644
index fe8c6e1647f8..000000000000
--- a/drivers/input/touchscreen/msg21xx_ts.c
+++ /dev/null
@@ -1,2260 +0,0 @@
-/*
- * MStar MSG21XX touchscreen driver
- *
- * Copyright (c) 2006-2012 MStar Semiconductor, Inc.
- *
- * 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
- * (at your option) any later version.
- *
- * 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/kernel.h>
-#include <linux/input.h>
-#include <linux/input/mt.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
-#include <linux/sysfs.h>
-#include <linux/init.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/debugfs.h>
-#include <linux/regulator/consumer.h>
-
-#if defined(CONFIG_FB)
-#include <linux/notifier.h>
-#include <linux/fb.h>
-#endif
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
-#include <linux/input/vir_ps.h>
-#endif
-
-/* Macro Definition */
-
-#define TOUCH_DRIVER_DEBUG 0
-#if (TOUCH_DRIVER_DEBUG == 1)
-#define DBG(fmt, arg...) pr_info(fmt, ##arg)
-#else
-#define DBG(fmt, arg...)
-#endif
-
-/* Constant Value & Variable Definition */
-
-#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 MSTAR_DEBUG_DIR_NAME "ts_debug"
-
-#define MSG_FW_FILE_MAJOR_VERSION(x) \
- (((x)->data[0x7f4f] << 8) + ((x)->data[0x7f4e]))
-
-#define MSG_FW_FILE_MINOR_VERSION(x) \
- (((x)->data[0x7f51] << 8) + ((x)->data[0x7f50]))
-
-/*
- * Note.
- * Please do not change the below setting.
- */
-#define TPD_WIDTH (2048)
-#define TPD_HEIGHT (2048)
-
-#ifdef FIRMWARE_AUTOUPDATE
-enum {
- SWID_START = 1,
- SWID_TRULY = SWID_START,
- SWID_NULL,
-};
-
-static unsigned char MSG_FIRMWARE[1][33*1024] = { {
- #include "msg21xx_truly_update_bin.h"
- }
-};
-#endif
-
-#define CONFIG_TP_HAVE_KEY
-#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 DEMO_MODE_PACKET_LENGTH (8)
-
-#define TP_PRINT
-
-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 unsigned short fw_file_major, fw_file_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];
- u8 fw_version_major;
- u8 fw_version_minor;
- u32 irq_gpio;
- u32 irq_gpio_flags;
- u32 reset_gpio;
- u32 reset_gpio_flags;
- 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);
- u8 ic_type;
- u32 button_map[MAX_BUTTONS];
- u32 num_buttons;
- u32 hard_reset_delay_ms;
- u32 post_hard_reset_delay_ms;
- bool updating_fw;
-};
-
-/* Touch Data Type Definition */
-struct touchPoint_t {
- unsigned short x;
- unsigned short y;
-};
-
-struct touchInfo_t {
- struct touchPoint_t *point;
- unsigned char count;
- unsigned char keycode;
-};
-
-struct msg21xx_ts_data {
- struct i2c_client *client;
- struct input_dev *input_dev;
- struct msg21xx_ts_platform_data *pdata;
- struct regulator *vdd;
- struct regulator *vcc_i2c;
- bool suspended;
-#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;
- struct touchInfo_t info;
-};
-
-#if defined(CONFIG_FB)
-static int fb_notifier_callback(struct notifier_block *self,
- unsigned long event, void *data);
-#endif
-
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
-static unsigned char bEnableTpProximity;
-static unsigned char bFaceClosingTp;
-#endif
-
-#ifdef TP_PRINT
-static int tp_print_proc_read(struct msg21xx_ts_data *ts_data);
-static void tp_print_create_entry(struct msg21xx_ts_data *ts_data);
-#endif
-
-static void _ReadBinConfig(struct msg21xx_ts_data *ts_data);
-static unsigned int _CalMainCRC32(struct msg21xx_ts_data *ts_data);
-
-static struct mutex msg21xx_mutex;
-
-enum EMEM_TYPE_t {
- EMEM_ALL = 0,
- EMEM_MAIN,
- EMEM_INFO,
-};
-
-/* Function Definition */
-
-static unsigned int _CRC_doReflect(unsigned int ref, signed char ch)
-{
- 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;
-}
-
-static unsigned int _CRC_getValue(unsigned int text, unsigned int prevCRC)
-{
- unsigned int ulCRC = prevCRC;
-
- ulCRC = (ulCRC >> 8) ^ crc32_table[(ulCRC & 0xFF) ^ text];
-
- return ulCRC;
-}
-
-static void _CRC_initTable(void)
-{
- 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 msg21xx_reset_hw(struct msg21xx_ts_platform_data *pdata)
-{
- gpio_direction_output(pdata->reset_gpio, 1);
- gpio_set_value_cansleep(pdata->reset_gpio, 0);
- /* Note that the RST must be in LOW 10ms at least */
- usleep(pdata->hard_reset_delay_ms * 1000);
- gpio_set_value_cansleep(pdata->reset_gpio, 1);
- /* Enable the interrupt service thread/routine for INT after 50ms */
- usleep(pdata->post_hard_reset_delay_ms * 1000);
-}
-
-static int read_i2c_seq(struct msg21xx_ts_data *ts_data, 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 (ts_data->client != NULL) {
- rc = i2c_transfer(ts_data->client->adapter, msgs, 1);
- if (rc < 0)
- dev_err(&ts_data->client->dev,
- "%s error %d\n", __func__, rc);
- } else {
- dev_err(&ts_data->client->dev, "ts_data->client is NULL\n");
- }
-
- return rc;
-}
-
-static int write_i2c_seq(struct msg21xx_ts_data *ts_data, unsigned char addr,
- unsigned char *buf, unsigned short size)
-{
- 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 (ts_data->client != NULL) {
- rc = i2c_transfer(ts_data->client->adapter, msgs, 1);
- if (rc < 0)
- dev_err(&ts_data->client->dev,
- "%s error %d\n", __func__, rc);
- } else {
- dev_err(&ts_data->client->dev, "ts_data->client is NULL\n");
- }
-
- return rc;
-}
-
-static unsigned short read_reg(struct msg21xx_ts_data *ts_data,
- unsigned char bank, unsigned char addr)
-{
- unsigned char tx_data[3] = {0x10, bank, addr};
- unsigned char rx_data[2] = {0};
-
- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, tx_data, sizeof(tx_data));
- read_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, rx_data, sizeof(rx_data));
-
- return rx_data[1] << 8 | rx_data[0];
-}
-
-static void write_reg(struct msg21xx_ts_data *ts_data, unsigned char bank,
- unsigned char addr,
- unsigned short data)
-{
- unsigned char tx_data[5] = {0x10, bank, addr, data & 0xFF, data >> 8};
-
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 5);
- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, tx_data, sizeof(tx_data));
-}
-
-static void write_reg_8bit(struct msg21xx_ts_data *ts_data, unsigned char bank,
- unsigned char addr,
- unsigned char data)
-{
- unsigned char tx_data[4] = {0x10, bank, addr, data};
-
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 4);
- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, tx_data, sizeof(tx_data));
-}
-
-static void dbbusDWIICEnterSerialDebugMode(struct msg21xx_ts_data *ts_data)
-{
- unsigned char data[5];
-
- /* Enter the Serial Debug Mode */
- data[0] = 0x53;
- data[1] = 0x45;
- data[2] = 0x52;
- data[3] = 0x44;
- data[4] = 0x42;
-
- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data));
-}
-
-static void dbbusDWIICStopMCU(struct msg21xx_ts_data *ts_data)
-{
- unsigned char data[1];
-
- /* Stop the MCU */
- data[0] = 0x37;
-
- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data));
-}
-
-static void dbbusDWIICIICUseBus(struct msg21xx_ts_data *ts_data)
-{
- unsigned char data[1];
-
- /* IIC Use Bus */
- data[0] = 0x35;
-
- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data));
-}
-
-static void dbbusDWIICIICReshape(struct msg21xx_ts_data *ts_data)
-{
- unsigned char data[1];
-
- /* IIC Re-shape */
- data[0] = 0x71;
-
- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data));
-}
-
-static unsigned char msg21xx_get_ic_type(struct msg21xx_ts_data *ts_data)
-{
- unsigned char ic_type = 0;
- unsigned char bank;
- unsigned char addr;
-
- msg21xx_reset_hw(ts_data->pdata);
- dbbusDWIICEnterSerialDebugMode(ts_data);
- dbbusDWIICStopMCU(ts_data);
- dbbusDWIICIICUseBus(ts_data);
- dbbusDWIICIICReshape(ts_data);
- msleep(300);
-
- /* stop mcu */
- write_reg_8bit(ts_data, 0x0F, 0xE6, 0x01);
- /* disable watch dog */
- write_reg(ts_data, 0x3C, 0x60, 0xAA55);
- /* get ic type */
- bank = MSTAR_CHIPTOP_REGISTER_BANK;
- addr = MSTAR_CHIPTOP_REGISTER_ICTYPE;
- ic_type = (0xff)&(read_reg(ts_data, bank, addr));
-
- if (ic_type != ts_data->pdata->ic_type)
- ic_type = 0;
-
- msg21xx_reset_hw(ts_data->pdata);
-
- return ic_type;
-}
-
-static int msg21xx_read_firmware_id(struct msg21xx_ts_data *ts_data)
-{
- unsigned char command[3] = { 0x53, 0x00, 0x2A};
- unsigned char response[4] = { 0 };
-
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(ts_data, ts_data->client->addr, command, sizeof(command));
- read_i2c_seq(ts_data, ts_data->client->addr, response,
- sizeof(response));
- mutex_unlock(&msg21xx_mutex);
- ts_data->pdata->fw_version_major = (response[1]<<8) + response[0];
- ts_data->pdata->fw_version_minor = (response[3]<<8) + response[2];
-
- dev_info(&ts_data->client->dev, "major num = %d, minor num = %d\n",
- ts_data->pdata->fw_version_major,
- ts_data->pdata->fw_version_minor);
-
- return 0;
-}
-
-static int firmware_erase_c33(struct msg21xx_ts_data *ts_data,
- enum EMEM_TYPE_t emem_type)
-{
- /* stop mcu */
- write_reg(ts_data, 0x0F, 0xE6, 0x0001);
-
- /* disable watch dog */
- write_reg_8bit(ts_data, 0x3C, 0x60, 0x55);
- write_reg_8bit(ts_data, 0x3C, 0x61, 0xAA);
-
- /* set PROGRAM password */
- write_reg_8bit(ts_data, 0x16, 0x1A, 0xBA);
- write_reg_8bit(ts_data, 0x16, 0x1B, 0xAB);
-
- write_reg_8bit(ts_data, 0x16, 0x18, 0x80);
-
- if (emem_type == EMEM_ALL)
- write_reg_8bit(ts_data, 0x16, 0x08, 0x10);
-
- write_reg_8bit(ts_data, 0x16, 0x18, 0x40);
- msleep(20);
-
- /* clear pce */
- write_reg_8bit(0x16, 0x18, 0x80);
-
- /* erase trigger */
- if (emem_type == EMEM_MAIN)
- write_reg_8bit(ts_data, 0x16, 0x0E, 0x04); /* erase main */
- else
- write_reg_8bit(0x16, 0x0E, 0x08); /* erase all block */
-
- return 1;
-}
-
-static void _ReadBinConfig(void);
-static unsigned int _CalMainCRC32(void);
-
-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;
- write_reg_8bit(ts_data, 0x16, 0x0E, 0x08); /* erase all block */
-
- return 0;
-}
-
-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;
- bool fw_upgrade = false;
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
-
- crc_main = 0xffffffff;
- crc_info = 0xffffffff;
-
- msg21xx_reset_hw(ts_data->pdata);
-
- msg21xx_read_firmware_id(ts_data);
- _ReadBinConfig(ts_data);
- if ((main_sw_id == info_sw_id) &&
- (_CalMainCRC32(ts_data) == bin_conf_crc32) &&
- (fw_file_major == ts_data->pdata->fw_version_major) &&
- (fw_file_minor > ts_data->pdata->fw_version_minor)) {
- fw_upgrade = true;
- }
-
- if (!fw_upgrade && !isForce) {
- dev_dbg(dev, "no need to update\n");
- msg21xx_reset_hw(ts_data->pdata);
- return size;
- }
- msg21xx_reset_hw(ts_data->pdata);
- msleep(300);
-
- dbbusDWIICEnterSerialDebugMode(ts_data);
- dbbusDWIICStopMCU(ts_data);
- dbbusDWIICIICUseBus(ts_data);
- dbbusDWIICIICReshape(ts_data);
- msleep(300);
-
- /* erase main */
- firmware_erase_c33(ts_data, EMEM_MAIN);
- msleep(1000);
-
- msg21xx_reset_hw(ts_data->pdata);
- dbbusDWIICEnterSerialDebugMode(ts_data);
- dbbusDWIICStopMCU(ts_data);
- dbbusDWIICIICUseBus(ts_data);
- dbbusDWIICIICReshape(ts_data);
- msleep(300);
- /*
- * Program
- */
- /* polling 0x3CE4 is 0x1C70 */
- if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
- do {
- reg_data = read_reg(ts_data, 0x3C, 0xE4);
- } while (reg_data != 0x1C70);
- }
-
- switch (emem_type) {
- case EMEM_ALL:
- write_reg(ts_data, 0x3C, 0xE4, 0xE38F); /* for all-blocks */
- break;
- case EMEM_MAIN:
- write_reg(ts_data, 0x3C, 0xE4, 0x7731); /* for main block */
- break;
- case EMEM_INFO:
- write_reg(ts_data, 0x3C, 0xE4, 0x7731); /* for info block */
-
- write_reg_8bit(ts_data, 0x0F, 0xE6, 0x01);
-
- write_reg_8bit(ts_data, 0x3C, 0xE4, 0xC5);
- write_reg_8bit(ts_data, 0x3C, 0xE5, 0x78);
-
- write_reg_8bit(ts_data, MSTAR_CHIPTOP_REGISTER_BANK,
- 0x04, 0x9F);
- write_reg_8bit(ts_data, MSTAR_CHIPTOP_REGISTER_BANK,
- 0x05, 0x82);
-
- write_reg_8bit(ts_data, 0x0F, 0xE6, 0x00);
- msleep(100);
- break;
- }
-
- /* polling 0x3CE4 is 0x2F43 */
- do {
- reg_data = read_reg(ts_data, 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, ts_data->client->addr,
- &fw_bin_data[i][j * 128], 128);
- msleep(100);
-
- /* polling 0x3CE4 is 0xD0BC */
- do {
- reg_data = read_reg(ts_data, 0x3C, 0xE4);
- } while (reg_data != 0xD0BC);
-
- write_reg(ts_data, 0x3C, 0xE4, 0x2F43);
- }
-
- if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
- /* write file done and check crc */
- write_reg(ts_data, 0x3C, 0xE4, 0x1380);
- }
- msleep(20);
-
- if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
- /* polling 0x3CE4 is 0x9432 */
- do {
- reg_data = read_reg(ts_data, 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(ts_data, 0x3C, 0x80);
- crc_main_tp = (crc_main_tp << 16) |
- read_reg(ts_data, 0x3C, 0x82);
-
- /* CRC Info from TP */
- crc_info_tp = read_reg(ts_data, 0x3C, 0xA0);
- crc_info_tp = (crc_info_tp << 16) |
- read_reg(ts_data, 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) {
- dev_err(dev, "update_C33 failed\n");
- msg21xx_reset_hw(ts_data->pdata);
- return 0;
- }
-
- dev_dbg(dev, "update_C33 OK\n");
- msg21xx_reset_hw(ts_data->pdata);
- return size;
-}
-
-static unsigned int _CalMainCRC32(struct msg21xx_ts_data *ts_data)
-{
- unsigned int ret = 0;
- unsigned short reg_data = 0;
-
- msg21xx_reset_hw(ts_data->pdata);
-
- dbbusDWIICEnterSerialDebugMode(ts_data);
- dbbusDWIICStopMCU(ts_data);
- dbbusDWIICIICUseBus(ts_data);
- dbbusDWIICIICReshape(ts_data);
- msleep(100);
-
- /* Stop MCU */
- write_reg(ts_data, 0x0F, 0xE6, 0x0001);
-
- /* Stop Watchdog */
- write_reg_8bit(ts_data, 0x3C, 0x60, 0x55);
- write_reg_8bit(ts_data, 0x3C, 0x61, 0xAA);
-
- /* cmd */
- write_reg(ts_data, 0x3C, 0xE4, 0xDF4C);
- write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x7d60);
- /* TP SW reset */
- write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x829F);
-
- /* MCU run */
- write_reg(ts_data, 0x0F, 0xE6, 0x0000);
-
- /* polling 0x3CE4 */
- do {
- reg_data = read_reg(ts_data, 0x3C, 0xE4);
- } while (reg_data != 0x9432);
-
- /* Cal CRC Main from TP */
- ret = read_reg(ts_data, 0x3C, 0x80);
- ret = (ret << 16) | read_reg(ts_data, 0x3C, 0x82);
-
- dev_dbg(&ts_data->client->dev,
- "[21xxA]:Current main crc32=0x%x\n", ret);
- return ret;
-}
-
-static void _ReadBinConfig(struct msg21xx_ts_data *ts_data)
-{
- unsigned char dbbus_tx_data[5] = {0};
- unsigned char dbbus_rx_data[4] = {0};
- unsigned short reg_data = 0;
-
- msg21xx_reset_hw(ts_data->pdata);
-
- dbbusDWIICEnterSerialDebugMode(ts_data);
- dbbusDWIICStopMCU(ts_data);
- dbbusDWIICIICUseBus(ts_data);
- dbbusDWIICIICReshape(ts_data);
- msleep(100);
-
- /* Stop MCU */
- write_reg(ts_data, 0x0F, 0xE6, 0x0001);
-
- /* Stop Watchdog */
- write_reg_8bit(ts_data, 0x3C, 0x60, 0x55);
- write_reg_8bit(ts_data, 0x3C, 0x61, 0xAA);
-
- /* cmd */
- write_reg(ts_data, 0x3C, 0xE4, 0xA4AB);
- write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x7d60);
-
- /* TP SW reset */
- write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x829F);
-
- /* MCU run */
- write_reg(ts_data, 0x0F, 0xE6, 0x0000);
-
- /* polling 0x3CE4 */
- do {
- reg_data = read_reg(ts_data, 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, ts_data->client->addr, &dbbus_tx_data[0], 5);
- read_i2c_seq(ts_data, 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, ts_data->client->addr, &dbbus_tx_data[0], 5);
- read_i2c_seq(ts_data, ts_data->client->addr, &dbbus_rx_data[0], 4);
- bin_conf_crc32 = (dbbus_rx_data[0] << 24) |
- (dbbus_rx_data[1] << 16) |
- (dbbus_rx_data[2] << 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, ts_data->client->addr, &dbbus_tx_data[0], 5);
- read_i2c_seq(ts_data, 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);
- }
-
- dev_dbg(&ts_data->client->dev,
- "[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 ssize_t firmware_update_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
-
- return snprintf(buf, 3, "%d\n", ts_data->pdata->updating_fw);
-}
-
-static ssize_t firmware_update_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t size)
-{
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
-
- ts_data->pdata->updating_fw = true;
- disable_irq(ts_data->client->irq);
-
- size = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, false);
-
- enable_irq(ts_data->client->irq);
- ts_data->pdata->updating_fw = false;
-
- return size;
-}
-
-static DEVICE_ATTR(update, (S_IRUGO | S_IWUSR),
- firmware_update_show,
- firmware_update_store);
-
-static int prepare_fw_data(struct device *dev)
-{
- int count;
- int i;
- int ret;
- const struct firmware *fw = NULL;
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
-
- ret = request_firmware(&fw, ts_data->pdata->fw_name, dev);
- if (ret < 0) {
- dev_err(dev, "Request firmware failed - %s (%d)\n",
- ts_data->pdata->fw_name, ret);
- return ret;
- }
-
- count = fw->size / 1024;
-
- for (i = 0; i < count; i++)
- memcpy(fw_bin_data[i], fw->data + (i * 1024), 1024);
-
- fw_file_major = MSG_FW_FILE_MAJOR_VERSION(fw);
- fw_file_minor = MSG_FW_FILE_MINOR_VERSION(fw);
- dev_dbg(dev, "New firmware: %d.%d",
- fw_file_major, fw_file_minor);
-
- return fw->size;
-}
-
-static ssize_t firmware_update_smart_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t size)
-{
- int ret;
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
-
- ret = prepare_fw_data(dev);
- if (ret < 0) {
- dev_err(dev, "Request firmware failed -(%d)\n", ret);
- return ret;
- }
- ts_data->pdata->updating_fw = true;
- disable_irq(ts_data->client->irq);
-
- ret = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, false);
- if (ret == 0)
- dev_err(dev, "firmware_update_c33 ret = %d\n", ret);
-
- enable_irq(ts_data->client->irq);
- ts_data->pdata->updating_fw = false;
-
- return ret;
-}
-
-static ssize_t firmware_force_update_smart_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t size)
-{
- int ret;
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
-
- ret = prepare_fw_data(dev);
- if (ret < 0) {
- dev_err(dev, "Request firmware failed -(%d)\n", ret);
- return ret;
- }
- ts_data->pdata->updating_fw = true;
- disable_irq(ts_data->client->irq);
-
- ret = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, true);
- if (ret == 0)
- dev_err(dev, "firmware_update_c33 et = %d\n", ret);
-
- enable_irq(ts_data->client->irq);
- ts_data->pdata->updating_fw = false;
-
- return ret;
-}
-
-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 msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
-
- msg21xx_read_firmware_id(ts_data);
- return snprintf(buf, sizeof(char) * 8, "%03d%03d\n",
- ts_data->pdata->fw_version_major,
- ts_data->pdata->fw_version_minor);
-}
-
-static DEVICE_ATTR(version, S_IRUGO,
- firmware_version_show,
- NULL);
-
-
-static ssize_t msg21xx_fw_name_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
-
- return snprintf(buf, MSTAR_FW_NAME_MAX_LEN - 1,
- "%s\n", ts_data->pdata->fw_name);
-}
-
-static ssize_t msg21xx_fw_name_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t size)
-{
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
-
- if (size > MSTAR_FW_NAME_MAX_LEN - 1)
- return -EINVAL;
-
- strlcpy(ts_data->pdata->fw_name, buf, size);
- if (ts_data->pdata->fw_name[size - 1] == '\n')
- ts_data->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_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t size)
-{
- int count = size / 1024;
- int i;
-
- for (i = 0; i < count; i++)
- memcpy(fw_bin_data[i], buf + (i * 1024), 1024);
-
- if (buf != NULL)
- dev_dbg(dev, "buf[0] = %c\n", buf[0]);
-
- return size;
-}
-
-static DEVICE_ATTR(data, S_IWUSR, NULL, firmware_data_store);
-
-static ssize_t tp_print_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
-
- tp_print_proc_read(ts_data);
-
- return snprintf(buf, 3, "%d\n", ts_data->suspended);
-}
-
-static ssize_t tp_print_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t size)
-{
- return size;
-}
-
-static DEVICE_ATTR(tpp, (S_IRUGO | S_IWUSR),
- tp_print_show, tp_print_store);
-
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
-static void _msg_enable_proximity(void)
-{
- unsigned char tx_data[4] = {0};
-
- 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)
-{
- unsigned char tx_data[4] = {0};
-
- 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;
-}
-
-static void tsps_msg21xx_enable(int en)
-{
- if (en)
- _msg_enable_proximity();
- else
- _msg_disable_proximity();
-}
-
-static int tsps_msg21xx_data(void)
-{
- return bFaceClosingTp;
-}
-#endif
-
-static int msg21xx_pinctrl_init(struct msg21xx_ts_data *ts_data)
-{
- int retval;
-
- /* Get pinctrl if target uses pinctrl */
- ts_data->ts_pinctrl = devm_pinctrl_get(&(ts_data->client->dev));
- if (IS_ERR_OR_NULL(ts_data->ts_pinctrl)) {
- retval = PTR_ERR(ts_data->ts_pinctrl);
- dev_dbg(&ts_data->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(&ts_data->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(&ts_data->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(&ts_data->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;
-}
-
-static unsigned char calculate_checksum(unsigned char *msg, int length)
-{
- int checksum = 0, i;
-
- for (i = 0; i < length; i++)
- checksum += msg[i];
-
- return (unsigned char)((-checksum) & 0xFF);
-}
-
-static int parse_info(struct msg21xx_ts_data *ts_data)
-{
- 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, ts_data->client->addr, &data[0],
- DEMO_MODE_PACKET_LENGTH);
- mutex_unlock(&msg21xx_mutex);
- checksum = calculate_checksum(&data[0], (DEMO_MODE_PACKET_LENGTH-1));
- dev_dbg(&ts_data->client->dev, "check sum: [%x] == [%x]?\n",
- data[DEMO_MODE_PACKET_LENGTH-1], checksum);
-
- if (data[DEMO_MODE_PACKET_LENGTH-1] != checksum) {
- dev_err(&ts_data->client->dev, "WRONG CHECKSUM\n");
- return -EINVAL;
- }
-
- if (data[0] != 0x52) {
- dev_err(&ts_data->client->dev, "WRONG HEADER\n");
- return -EINVAL;
- }
-
- ts_data->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)) {
- ts_data->info.keycode = 0xFF;
- } else if ((data[5] == 1) || (data[5] == 2) ||
- (data[5] == 4) || (data[5] == 8)) {
- ts_data->info.keycode = data[5] >> 1;
-
- dev_dbg(&ts_data->client->dev,
- "ts_data->info.keycode index %d\n",
- ts_data->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 {
- dev_err(&ts_data->client->dev, "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)) {
- ts_data->info.point[0].x =
- x * ts_data->pdata->x_max / TPD_WIDTH;
- ts_data->info.point[0].y =
- y * ts_data->pdata->y_max / TPD_HEIGHT;
- ts_data->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);
- ts_data->info.point[0].x =
- x * ts_data->pdata->x_max / TPD_WIDTH;
- ts_data->info.point[0].y =
- y * ts_data->pdata->y_max / TPD_HEIGHT;
- ts_data->info.point[1].x =
- x2 * ts_data->pdata->x_max / TPD_WIDTH;
- ts_data->info.point[1].y =
- y2 * ts_data->pdata->y_max / TPD_HEIGHT;
- ts_data->info.count = ts_data->pdata->num_max_touches;
- }
- }
-
- return 0;
-}
-
-static void touch_driver_touch_released(struct msg21xx_ts_data *ts_data)
-{
- int i;
-
- for (i = 0; i < ts_data->pdata->num_max_touches; i++) {
- input_mt_slot(ts_data->input_dev, i);
- input_mt_report_slot_state(ts_data->input_dev,
- MT_TOOL_FINGER, 0);
- }
-
- input_report_key(ts_data->input_dev, BTN_TOUCH, 0);
- input_report_key(ts_data->input_dev, BTN_TOOL_FINGER, 0);
- input_sync(ts_data->input_dev);
-}
-
-/* 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)
-{
- int i = 0;
- static int last_keycode = 0xFF;
- static int last_count;
- struct msg21xx_ts_data *ts_data = dev_id;
-
- ts_data->info.count = 0;
- if (parse_info(ts_data) == 0) {
- if (ts_data->info.keycode != 0xFF) { /* key touch pressed */
- if (ts_data->info.keycode <
- ts_data->pdata->num_buttons) {
- if (ts_data->info.keycode != last_keycode) {
- dev_dbg(&ts_data->client->dev,
- "key touch pressed");
-
- input_report_key(ts_data->input_dev,
- BTN_TOUCH, 1);
- input_report_key(ts_data->input_dev,
- ts_data->pdata->button_map[
- ts_data->info.keycode], 1);
-
- last_keycode = ts_data->info.keycode;
- } else {
- /* pass duplicate key-pressing */
- dev_dbg(&ts_data->client->dev,
- "REPEATED KEY\n");
- }
- } else {
- dev_dbg(&ts_data->client->dev, "WRONG KEY\n");
- }
- } else { /* key touch released */
- if (last_keycode != 0xFF) {
- dev_dbg(&ts_data->client->dev, "key touch released");
-
- input_report_key(ts_data->input_dev,
- BTN_TOUCH, 0);
- input_report_key(ts_data->input_dev,
- ts_data->pdata->button_map[last_keycode],
- 0);
-
- last_keycode = 0xFF;
- }
- }
-
- if (ts_data->info.count > 0) { /* point touch pressed */
- for (i = 0; i < ts_data->info.count; i++) {
- input_mt_slot(ts_data->input_dev, i);
- input_mt_report_slot_state(ts_data->input_dev,
- MT_TOOL_FINGER, 1);
- input_report_abs(ts_data->input_dev,
- ABS_MT_TOUCH_MAJOR, 1);
- input_report_abs(ts_data->input_dev,
- ABS_MT_POSITION_X,
- ts_data->info.point[i].x);
- input_report_abs(ts_data->input_dev,
- ABS_MT_POSITION_Y,
- ts_data->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,
- }
-
- if (last_count > ts_data->info.count) {
- for (i = ts_data->info.count;
- i < ts_data->pdata->num_max_touches;
- i++) {
- input_mt_slot(ts_data->input_dev, i);
- input_mt_report_slot_state(ts_data->input_dev,
- MT_TOOL_FINGER, 0);
- }
- }
- last_count = ts_data->info.count;
-
- input_report_key(ts_data->input_dev, BTN_TOUCH,
- ts_data->info.count > 0);
- input_report_key(ts_data->input_dev, BTN_TOOL_FINGER,
- ts_data->info.count > 0);
-
- input_sync(ts_data->input_dev);
- }
-
- return IRQ_HANDLED;
-}
-
-static int msg21xx_ts_power_init(struct msg21xx_ts_data *ts_data, bool init)
-{
- int rc;
-
- if (init) {
- ts_data->vdd = regulator_get(&ts_data->client->dev,
- "vdd");
- if (IS_ERR(ts_data->vdd)) {
- rc = PTR_ERR(ts_data->vdd);
- dev_err(&ts_data->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(&ts_data->client->dev,
- "Regulator set_vtg failed vdd rc=%d\n",
- rc);
- goto reg_vdd_put;
- }
- }
-
- ts_data->vcc_i2c = regulator_get(&ts_data->client->dev,
- "vcc_i2c");
- if (IS_ERR(ts_data->vcc_i2c)) {
- rc = PTR_ERR(ts_data->vcc_i2c);
- dev_err(&ts_data->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(&ts_data->client->dev,
- "Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
- goto reg_vcc_i2c_put;
- }
- }
- } else {
- 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;
-
-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;
-}
-
-static int msg21xx_ts_power_on(struct msg21xx_ts_data *ts_data, bool on)
-{
- int rc;
-
- if (!on)
- goto power_off;
-
- rc = regulator_enable(ts_data->vdd);
- if (rc) {
- dev_err(&ts_data->client->dev,
- "Regulator vdd enable failed rc=%d\n", rc);
- return rc;
- }
-
- rc = regulator_enable(ts_data->vcc_i2c);
- if (rc) {
- dev_err(&ts_data->client->dev,
- "Regulator vcc_i2c enable failed rc=%d\n", rc);
- regulator_disable(ts_data->vdd);
- }
-
- return rc;
-
- DBG("*** %s ***\n", __func__);
- rc = regulator_disable(vdd);
-power_off:
- rc = regulator_disable(ts_data->vdd);
- if (rc) {
- dev_err(&ts_data->client->dev,
- "Regulator vdd disable failed rc=%d\n", rc);
- return rc;
- }
-
- rc = regulator_disable(ts_data->vcc_i2c);
- if (rc) {
- dev_err(&ts_data->client->dev,
- "Regulator vcc_i2c disable failed rc=%d\n", rc);
- rc = regulator_enable(ts_data->vdd);
- }
-
- return rc;
-}
-
-static int msg21xx_ts_gpio_configure(struct msg21xx_ts_data *ts_data, bool on)
-{
- int ret = 0;
-
- if (!on)
- goto pwr_deinit;
-
- if (gpio_is_valid(ts_data->pdata->irq_gpio)) {
- ret = gpio_request(ts_data->pdata->irq_gpio,
- "msg21xx_irq_gpio");
- if (ret) {
- dev_err(&ts_data->client->dev,
- "Failed to request GPIO[%d], %d\n",
- ts_data->pdata->irq_gpio, ret);
- goto err_irq_gpio_req;
- }
- ret = gpio_direction_input(ts_data->pdata->irq_gpio);
- if (ret) {
- dev_err(&ts_data->client->dev,
- "Failed to set direction for gpio[%d], %d\n",
- ts_data->pdata->irq_gpio, ret);
- goto err_irq_gpio_dir;
- }
- gpio_set_value_cansleep(ts_data->pdata->irq_gpio, 1);
- } else {
- dev_err(&ts_data->client->dev, "irq gpio not provided\n");
- goto err_irq_gpio_req;
- }
-
- if (gpio_is_valid(ts_data->pdata->reset_gpio)) {
- ret = gpio_request(ts_data->pdata->reset_gpio,
- "msg21xx_reset_gpio");
- if (ret) {
- dev_err(&ts_data->client->dev,
- "Failed to request GPIO[%d], %d\n",
- ts_data->pdata->reset_gpio, ret);
- 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;
- /* power on TP */
- ret = gpio_direction_output(
- ts_data->pdata->reset_gpio, 1);
- if (ret) {
- dev_err(&ts_data->client->dev,
- "Failed to set direction for GPIO[%d], %d\n",
- ts_data->pdata->reset_gpio, ret);
- goto err_reset_gpio_dir;
- }
- msleep(100);
- gpio_set_value_cansleep(ts_data->pdata->reset_gpio, 0);
- msleep(20);
- gpio_set_value_cansleep(ts_data->pdata->reset_gpio, 1);
- msleep(200);
- } else {
- dev_err(&ts_data->client->dev, "reset gpio not provided\n");
- goto err_reset_gpio_req;
- }
-
- return 0;
-
-err_reset_gpio_dir:
- if (gpio_is_valid(ts_data->pdata->reset_gpio))
- gpio_free(ts_data->pdata->irq_gpio);
-err_reset_gpio_req:
-err_irq_gpio_dir:
- if (gpio_is_valid(ts_data->pdata->irq_gpio))
- gpio_free(ts_data->pdata->irq_gpio);
-err_irq_gpio_req:
- return ret;
-
-pwr_deinit:
- 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)) {
- gpio_set_value_cansleep(ts_data->pdata->reset_gpio, 0);
- ret = gpio_direction_input(ts_data->pdata->reset_gpio);
- if (ret)
- dev_err(&ts_data->client->dev,
- "Unable to set direction for gpio [%d]\n",
- ts_data->pdata->reset_gpio);
- gpio_free(ts_data->pdata->reset_gpio);
- }
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int msg21xx_ts_resume(struct device *dev)
-{
- int retval;
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
-
- if (!ts_data->suspended) {
- dev_info(dev, "msg21xx_ts already in resume\n");
- return 0;
- }
-
- mutex_lock(&ts_data->ts_mutex);
-
- retval = msg21xx_ts_power_on(ts_data, true);
- if (retval) {
- dev_err(dev, "msg21xx_ts power on 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_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(ts_data, 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);
- ts_data->suspended = false;
-
- mutex_unlock(&ts_data->ts_mutex);
-
- return 0;
-}
-
-static int msg21xx_ts_suspend(struct device *dev)
-{
- int retval;
- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
-
- if (ts_data->pdata->updating_fw) {
- dev_info(dev, "Firmware loading in progress\n");
- return 0;
- }
-
- if (ts_data->suspended) {
- dev_info(dev, "msg21xx_ts already in suspend\n");
- return 0;
- }
-
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- if (bEnableTpProximity) {
- dev_dbg(dev, "suspend bEnableTpProximity=%d\n",
- bEnableTpProximity);
- return 0;
- }
-#endif
-
- mutex_lock(&ts_data->ts_mutex);
-
- disable_irq(ts_data->client->irq);
-
- touch_driver_touch_released(ts_data);
-
- 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);
- mutex_unlock(&ts_data->ts_mutex);
- return retval;
- }
- }
-
- retval = msg21xx_ts_gpio_configure(ts_data, false);
- if (retval) {
- dev_err(dev, "Failed to put gpios in idle state %d",
- retval);
- mutex_unlock(&ts_data->ts_mutex);
- return retval;
- }
-
- retval = msg21xx_ts_power_on(ts_data, false);
- if (retval) {
- dev_err(dev, "msg21xx_ts power off failed");
- mutex_unlock(&ts_data->ts_mutex);
- return retval;
- }
-
- ts_data->suspended = true;
-
- mutex_unlock(&ts_data->ts_mutex);
-
- return 0;
-}
-#else
-static int msg21xx_ts_resume(struct device *dev)
-{
- return 0;
-}
-static int msg21xx_ts_suspend(struct device *dev)
-{
- return 0;
-}
-#endif
-
-static int msg21xx_debug_suspend_set(void *_data, u64 val)
-{
- struct msg21xx_ts_data *data = _data;
-
- mutex_lock(&data->input_dev->mutex);
-
- if (val)
- msg21xx_ts_suspend(&data->client->dev);
- else
- msg21xx_ts_resume(&data->client->dev);
-
- mutex_unlock(&data->input_dev->mutex);
-
- return 0;
-}
-
-static int msg21xx_debug_suspend_get(void *_data, u64 *val)
-{
- struct msg21xx_ts_data *data = _data;
-
- mutex_lock(&data->input_dev->mutex);
- *val = data->suspended;
- mutex_unlock(&data->input_dev->mutex);
-
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, msg21xx_debug_suspend_get,
- msg21xx_debug_suspend_set, "%lld\n");
-
-
-#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 msg21xx_ts_data *ts_data =
- container_of(self, struct msg21xx_ts_data, fb_notif);
-
- if (evdata && evdata->data && event == FB_EVENT_BLANK) {
- blank = evdata->data;
- if (*blank == FB_BLANK_UNBLANK)
- msg21xx_ts_resume(&ts_data->client->dev);
- else if (*blank == FB_BLANK_POWERDOWN)
- msg21xx_ts_suspend(&ts_data->client->dev);
- }
-
- return 0;
-}
-#endif
-
-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;
-
- rc = of_property_read_u32(np, "mstar,hard-reset-delay-ms",
- &temp_val);
- if (!rc)
- pdata->hard_reset_delay_ms = temp_val;
- else
- return rc;
-
- rc = of_property_read_u32(np, "mstar,post-hard-reset-delay-ms",
- &temp_val);
- if (!rc)
- pdata->post_hard_reset_delay_ms = temp_val;
- else
- 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;
-
- rc = of_property_read_u32(np, "mstar,ic-type", &temp_val);
- if (rc && (rc != -EINVAL))
- return rc;
-
- pdata->ic_type = temp_val;
-
- rc = of_property_read_u32(np, "mstar,num-max-touches", &temp_val);
- if (!rc)
- pdata->num_max_touches = temp_val;
- else
- return rc;
-
- prop = of_find_property(np, "mstar,button-map", NULL);
- if (prop) {
- pdata->num_buttons = prop->length / sizeof(temp_val);
- if (pdata->num_buttons > MAX_BUTTONS)
- return -EINVAL;
-
- rc = of_property_read_u32_array(np,
- "mstar,button-map", pdata->button_map,
- pdata->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, i;
- struct dentry *temp, *dir;
- struct input_dev *input_dev;
- struct msg21xx_ts_data *ts_data;
- struct msg21xx_ts_platform_data *pdata;
-
- 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;
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- dev_err(&client->dev, "I2C not supported\n");
- return -ENODEV;
- }
-
- ts_data = devm_kzalloc(&client->dev,
- sizeof(struct msg21xx_ts_data), GFP_KERNEL);
- if (!ts_data)
- return -ENOMEM;
-
- ts_data->client = client;
- ts_data->info.point = devm_kzalloc(&client->dev,
- sizeof(struct touchPoint_t) * pdata->num_max_touches,
- GFP_KERNEL);
- if (!ts_data->info.point) {
- dev_err(&client->dev, "Not enough memory\n");
- return -ENOMEM;
- }
-
- /* allocate an input device */
- input_dev = input_allocate_device();
- if (!input_dev) {
- ret = -ENOMEM;
- dev_err(&client->dev, "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;
-
- 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);
-
- ret = msg21xx_ts_power_init(ts_data, true);
- if (ret) {
- dev_err(&client->dev, "Mstar power init failed\n");
- return ret;
- }
-
- ret = msg21xx_ts_power_on(ts_data, true);
- if (ret) {
- dev_err(&client->dev, "Mstar power on failed\n");
- goto exit_deinit_power;
- }
-
- ret = msg21xx_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(ts_data->ts_pinctrl,
- ts_data->pinctrl_state_active);
- if (ret < 0)
- dev_err(&client->dev,
- "Failed to select %s pinatate %d\n",
- PINCTRL_STATE_ACTIVE, ret);
- }
-
- ret = msg21xx_ts_gpio_configure(ts_data, true);
- if (ret) {
- dev_err(&client->dev, "Failed to configure gpio %d\n", ret);
- goto exit_gpio_config;
- }
-
- if (msg21xx_get_ic_type(ts_data) == 0) {
- dev_err(&client->dev, "The current IC is not Mstar\n");
- ret = -1;
- goto err_wrong_ic_type;
- }
-
- mutex_init(&msg21xx_mutex);
- mutex_init(&ts_data->ts_mutex);
-
- /* 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);
-
- for (i = 0; i < pdata->num_buttons; i++)
- input_set_capability(input_dev, EV_KEY, pdata->button_map[i]);
-
- input_set_drvdata(input_dev, ts_data);
- i2c_set_clientdata(client, ts_data);
-
-#ifdef CONFIG_TP_HAVE_KEY
- {
- 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_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, pdata->num_max_touches, 0);
- if (ret) {
- dev_err(&client->dev,
- "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) {
- dev_err(&client->dev,
- "Unable to register ms-touchscreen input device\n");
- goto err_input_reg_dev;
- }
-
- /* version */
- if (device_create_file(&client->dev, &dev_attr_version) < 0) {
- dev_err(&client->dev,
- "Failed to create device file(%s)!\n",
- dev_attr_version.attr.name);
- goto err_create_fw_ver_file;
- }
- /* update */
- if (device_create_file(&client->dev, &dev_attr_update) < 0) {
- dev_err(&client->dev,
- "Failed to create device file(%s)!\n",
- dev_attr_update.attr.name);
- goto err_create_fw_update_file;
- }
- /* data */
- if (device_create_file(&client->dev, &dev_attr_data) < 0) {
- dev_err(&client->dev,
- "Failed to create device file(%s)!\n",
- dev_attr_data.attr.name);
- goto err_create_fw_data_file;
- }
- /* fw name */
- if (device_create_file(&client->dev, &dev_attr_fw_name) < 0) {
- dev_err(&client->dev,
- "Failed to create device file(%s)!\n",
- dev_attr_fw_name.attr.name);
- goto err_create_fw_name_file;
- }
- /* smart fw update */
- if (device_create_file(&client->dev, &dev_attr_update_fw) < 0) {
- dev_err(&client->dev,
- "Failed to create device file(%s)!\n",
- dev_attr_update_fw.attr.name);
- goto err_create_update_fw_file;
- }
- /* smart fw force update */
- if (device_create_file(&client->dev,
- &dev_attr_force_update_fw) < 0) {
- dev_err(&client->dev,
- "Failed to create device file(%s)!\n",
- dev_attr_force_update_fw.attr.name);
- goto err_create_force_update_fw_file;
- }
- dir = debugfs_create_dir(MSTAR_DEBUG_DIR_NAME, NULL);
- temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, dir,
- ts_data, &debug_suspend_fops);
- if (temp == NULL || IS_ERR(temp)) {
- dev_err(&client->dev,
- "debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
- goto free_debug_dir;
- }
-
-#ifdef TP_PRINT
- tp_print_create_entry(ts_data);
-#endif
-
- 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;
-
- disable_irq(client->irq);
-
-#if defined(CONFIG_FB)
- 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);
-#endif
-
- dev_dbg(&client->dev, "mstar touch screen registered\n");
- enable_irq(client->irq);
- return 0;
-
-err_req_irq:
- free_irq(client->irq, ts_data);
- device_remove_file(&client->dev, &dev_attr_data);
-free_debug_dir:
- debugfs_remove_recursive(dir);
-err_create_fw_data_file:
- device_remove_file(&client->dev, &dev_attr_update);
-err_create_fw_update_file:
- device_remove_file(&client->dev, &dev_attr_version);
-err_create_fw_name_file:
- device_remove_file(&client->dev, &dev_attr_fw_name);
-err_create_update_fw_file:
- device_remove_file(&client->dev, &dev_attr_update_fw);
-err_create_force_update_fw_file:
- device_remove_file(&client->dev, &dev_attr_force_update_fw);
-err_create_fw_ver_file:
- input_unregister_device(input_dev);
-
-err_input_reg_dev:
- input_free_device(input_dev);
- input_dev = NULL;
-err_input_allocate_dev:
- mutex_destroy(&msg21xx_mutex);
- mutex_destroy(&ts_data->ts_mutex);
-
-err_wrong_ic_type:
- msg21xx_ts_gpio_configure(ts_data, false);
-exit_gpio_config:
- 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)
- dev_err(&ts_data->client->dev,
- "Cannot get release pinctrl state\n");
- }
- }
- msg21xx_ts_power_on(ts_data, false);
-exit_deinit_power:
- msg21xx_ts_power_init(ts_data, false);
-err_free_mem:
- input_free_device(input_dev);
-
- return ret;
-}
-
-/* remove function is triggered when the input device is removed
- *from input sub-system
- */
-static int touch_driver_remove(struct i2c_client *client)
-{
- int retval = 0;
- struct msg21xx_ts_data *ts_data = i2c_get_clientdata(client);
-
- free_irq(ts_data->client->irq, ts_data);
- gpio_free(ts_data->pdata->irq_gpio);
- gpio_free(ts_data->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)
- dev_err(&ts_data->client->dev,
- "Cannot get release pinctrl state\n");
- }
- }
-
- input_unregister_device(ts_data->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 */
-};
-
-static const struct of_device_id msg21xx_match_table[] = {
- { .compatible = "mstar,msg21xx", },
- { },
-};
-
-MODULE_DEVICE_TABLE(i2c, touch_device_id);
-
-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,
-};
-
-module_i2c_driver(touch_device_driver);
-
-#ifdef TP_PRINT
-#include <linux/proc_fs.h>
-
-static unsigned short InfoAddr = 0x0F, PoolAddr = 0x10, TransLen = 256;
-static unsigned char row, units, cnt;
-
-static int tp_print_proc_read(struct msg21xx_ts_data *ts_data)
-{
- 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, ts_data->client->addr,
- &dbbus_tx_data[0], 3);
- read_i2c_seq(ts_data, 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(struct msg21xx_ts_data *ts_data)
-{
- 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, ts_data->client->addr, &dbbus_tx_data[0], 3);
- read_i2c_seq(ts_data, 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, ts_data->client->addr,
- &dbbus_tx_data[0], 3);
- read_i2c_seq(ts_data, 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(&ts_data->client->dev,
- &dev_attr_tpp) < 0)
- dev_err(&ts_data->client->dev, "Failed to create device file(%s)!\n",
- dev_attr_tpp.attr.name);
- }
-}
-#endif
-
-MODULE_AUTHOR("MStar Semiconductor, Inc.");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
index 5cbdc03ced9d..9ba0b7d93616 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
@@ -122,6 +122,7 @@ struct sde_smmu_client {
struct sde_module_power mp;
struct reg_bus_client *reg_bus_clt;
bool domain_attached;
+ bool domain_reattach;
int domain;
};
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c
index 9b1175d8f4a6..915126f09a27 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c
@@ -247,6 +247,14 @@ int sde_smmu_attach(struct sde_rot_data_type *mdata)
goto err;
}
sde_smmu->domain_attached = true;
+ if (sde_smmu->domain_reattach) {
+ SDEROT_DBG(
+ "domain[%i] re-attach\n",
+ i);
+ /* remove extra vote */
+ sde_smmu_enable_power(sde_smmu, false);
+ sde_smmu->domain_reattach = false;
+ }
SDEROT_DBG("iommu v2 domain[%i] attached\n", i);
}
} else {
@@ -292,6 +300,12 @@ int sde_smmu_detach(struct sde_rot_data_type *mdata)
arm_iommu_detach_device(sde_smmu->dev);
SDEROT_DBG("iommu domain[%i] detached\n", i);
sde_smmu->domain_attached = false;
+
+ /*
+ * since we are leaving the clock vote, on
+ * re-attaching do not vote for clocks
+ */
+ sde_smmu->domain_reattach = true;
}
else {
sde_smmu_enable_power(sde_smmu, false);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 9f5c67e850d4..26e57f3c5228 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -3095,7 +3095,6 @@ int mmc_resume_bus(struct mmc_host *host)
pr_debug("%s: Starting deferred resume\n", mmc_hostname(host));
spin_lock_irqsave(&host->lock, flags);
host->bus_resume_flags &= ~MMC_BUSRESUME_NEEDS_RESUME;
- host->rescan_disable = 0;
spin_unlock_irqrestore(&host->lock, flags);
mmc_bus_get(host);
@@ -4041,6 +4040,7 @@ EXPORT_SYMBOL(mmc_detect_card_removed);
void mmc_rescan(struct work_struct *work)
{
+ unsigned long flags;
struct mmc_host *host =
container_of(work, struct mmc_host, detect.work);
@@ -4049,8 +4049,12 @@ void mmc_rescan(struct work_struct *work)
host->trigger_card_event = false;
}
- if (host->rescan_disable)
+ spin_lock_irqsave(&host->lock, flags);
+ if (host->rescan_disable) {
+ spin_unlock_irqrestore(&host->lock, flags);
return;
+ }
+ spin_unlock_irqrestore(&host->lock, flags);
/* If there is a non-removable card registered, only scan once */
if ((host->caps & MMC_CAP_NONREMOVABLE) && host->rescan_entered)
@@ -4297,10 +4301,6 @@ int mmc_pm_notify(struct notifier_block *notify_block,
case PM_SUSPEND_PREPARE:
case PM_RESTORE_PREPARE:
spin_lock_irqsave(&host->lock, flags);
- if (mmc_bus_needs_resume(host)) {
- spin_unlock_irqrestore(&host->lock, flags);
- break;
- }
host->rescan_disable = 1;
spin_unlock_irqrestore(&host->lock, flags);
cancel_delayed_work_sync(&host->detect);
diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c
index a7546471e780..849722128ad2 100644
--- a/drivers/mmc/host/cmdq_hci.c
+++ b/drivers/mmc/host/cmdq_hci.c
@@ -845,7 +845,6 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err)
u32 dbr_set = 0;
status = cmdq_readl(cq_host, CQIS);
- cmdq_writel(cq_host, status, CQIS);
if (!status && !err)
return IRQ_NONE;
@@ -868,6 +867,17 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err)
if (ret)
pr_err("%s: %s: halt failed ret=%d\n",
mmc_hostname(mmc), __func__, ret);
+
+ /*
+ * Clear the CQIS after halting incase of error. This is done
+ * because if CQIS is cleared before halting, the CQ will
+ * continue with issueing commands for rest of requests with
+ * Doorbell rung. This will overwrite the Resp Arg register.
+ * So CQ must be halted first and then CQIS cleared incase
+ * of error
+ */
+ cmdq_writel(cq_host, status, CQIS);
+
cmdq_dumpregs(cq_host);
if (!err_info) {
@@ -956,13 +966,16 @@ skip_cqterri:
mrq->cmdq_req->resp_err = true;
pr_err("%s: Response error (0x%08x) from card !!!",
- mmc_hostname(mmc), status);
+ mmc_hostname(mmc), cmdq_readl(cq_host, CQCRA));
+
} else {
mrq->cmdq_req->resp_idx = cmdq_readl(cq_host, CQCRI);
mrq->cmdq_req->resp_arg = cmdq_readl(cq_host, CQCRA);
}
cmdq_finish_data(mmc, tag);
+ } else {
+ cmdq_writel(cq_host, status, CQIS);
}
if (status & CQIS_TCC) {
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 127a2602aa81..2cad8776411c 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -310,6 +310,9 @@ void sdhci_msm_writel_relaxed(u32 val, struct sdhci_host *host, u32 offset)
writel_relaxed(val, base_addr + offset);
}
+/* Timeout value to avoid infinite waiting for pwr_irq */
+#define MSM_PWR_IRQ_TIMEOUT_MS 5000
+
static const u32 tuning_block_64[] = {
0x00FF0FFF, 0xCCC3CCFF, 0xFFCC3CC3, 0xEFFEFFFE,
0xDDFFDFFF, 0xFBFFFBFF, 0xFF7FFFBF, 0xEFBDF777,
@@ -2779,8 +2782,10 @@ static void sdhci_msm_check_power_status(struct sdhci_host *host, u32 req_type)
*/
if (done)
init_completion(&msm_host->pwr_irq_completion);
- else
- wait_for_completion(&msm_host->pwr_irq_completion);
+ else if (!wait_for_completion_timeout(&msm_host->pwr_irq_completion,
+ msecs_to_jiffies(MSM_PWR_IRQ_TIMEOUT_MS)))
+ __WARN_printf("%s: request(%d) timed out waiting for pwr_irq\n",
+ mmc_hostname(host->mmc), req_type);
pr_debug("%s: %s: request %d done\n", mmc_hostname(host->mmc),
__func__, req_type);
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index fa76ca128e1b..e5bb870b5461 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -2390,8 +2390,6 @@ ppp_unregister_channel(struct ppp_channel *chan)
spin_lock_bh(&pn->all_channels_lock);
list_del(&pch->list);
spin_unlock_bh(&pn->all_channels_lock);
- put_net(pch->chan_net);
- pch->chan_net = NULL;
pch->file.dead = 1;
wake_up_interruptible(&pch->file.rwait);
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index 31b45912265f..b38515fc7ce7 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -212,21 +212,6 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return rc;
}
- /* device supports 48 bit addresses */
- rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
- if (rc) {
- dev_err(dev, "dma_set_mask_and_coherent(48) failed: %d\n", rc);
- rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
- if (rc) {
- dev_err(dev,
- "dma_set_mask_and_coherent(32) failed: %d\n",
- rc);
- goto if_free;
- }
- } else {
- wil->use_extended_dma_addr = 1;
- }
-
wil->pdev = pdev;
pci_set_drvdata(pdev, wil);
/* rollback to if_free */
@@ -240,6 +225,21 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
/* rollback to err_plat */
+ /* device supports 48bit addresses */
+ rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
+ if (rc) {
+ dev_err(dev, "dma_set_mask_and_coherent(48) failed: %d\n", rc);
+ rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ if (rc) {
+ dev_err(dev,
+ "dma_set_mask_and_coherent(32) failed: %d\n",
+ rc);
+ goto err_plat;
+ }
+ } else {
+ wil->use_extended_dma_addr = 1;
+ }
+
rc = pci_enable_device(pdev);
if (rc) {
wil_err(wil,
diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c
index 7c8b5e3e57a1..cd105a0bf5d1 100644
--- a/drivers/pci/host/pci-msm.c
+++ b/drivers/pci/host/pci-msm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, 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
@@ -2414,8 +2414,16 @@ static void msm_pcie_sel_debug_testcase(struct msm_pcie_dev_t *dev,
dev->res[base_sel - 1].base,
wr_offset, wr_mask, wr_value);
- msm_pcie_write_reg_field(dev->res[base_sel - 1].base,
- wr_offset, wr_mask, wr_value);
+ base_sel_size = resource_size(dev->res[base_sel - 1].resource);
+
+ if (wr_offset > base_sel_size - 4 ||
+ msm_pcie_check_align(dev, wr_offset))
+ PCIE_DBG_FS(dev,
+ "PCIe: RC%d: Invalid wr_offset: 0x%x. wr_offset should be no more than 0x%x\n",
+ dev->rc_idx, wr_offset, base_sel_size - 4);
+ else
+ msm_pcie_write_reg_field(dev->res[base_sel - 1].base,
+ wr_offset, wr_mask, wr_value);
break;
case 13: /* dump all registers of base_sel */
diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c
index 6e06fef81849..c3cb57ed6083 100644
--- a/drivers/phy/phy-qcom-ufs.c
+++ b/drivers/phy/phy-qcom-ufs.c
@@ -267,6 +267,14 @@ static int __ufs_qcom_phy_init_vreg(struct phy *phy,
char prop_name[MAX_PROP_NAME];
+ if (dev->of_node) {
+ snprintf(prop_name, MAX_PROP_NAME, "%s-supply", name);
+ if (!of_parse_phandle(dev->of_node, prop_name, 0)) {
+ dev_dbg(dev, "No vreg data found for %s\n", prop_name);
+ return optional ? err : -ENODATA;
+ }
+ }
+
vreg->name = kstrdup(name, GFP_KERNEL);
if (!vreg->name) {
err = -ENOMEM;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_client.c b/drivers/platform/msm/ipa/ipa_v2/ipa_client.c
index 66e329a03df7..74e7394a80b1 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 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
@@ -95,6 +95,46 @@ int ipa_disable_data_path(u32 clnt_hdl)
return res;
}
+int ipa2_enable_force_clear(u32 request_id, bool throttle_source,
+ u32 source_pipe_bitmask)
+{
+ struct ipa_enable_force_clear_datapath_req_msg_v01 req;
+ int result;
+
+ memset(&req, 0, sizeof(req));
+ req.request_id = request_id;
+ req.source_pipe_bitmask = source_pipe_bitmask;
+ if (throttle_source) {
+ req.throttle_source_valid = 1;
+ req.throttle_source = 1;
+ }
+ result = qmi_enable_force_clear_datapath_send(&req);
+ if (result) {
+ IPAERR("qmi_enable_force_clear_datapath_send failed %d\n",
+ result);
+ return result;
+ }
+
+ return 0;
+}
+
+int ipa2_disable_force_clear(u32 request_id)
+{
+ struct ipa_disable_force_clear_datapath_req_msg_v01 req;
+ int result;
+
+ memset(&req, 0, sizeof(req));
+ req.request_id = request_id;
+ result = qmi_disable_force_clear_datapath_send(&req);
+ if (result) {
+ IPAERR("qmi_disable_force_clear_datapath_send failed %d\n",
+ result);
+ return result;
+ }
+
+ return 0;
+}
+
static int ipa2_smmu_map_peer_bam(unsigned long dev)
{
phys_addr_t base;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
index b45e748b66a6..94d76db6f993 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
@@ -1803,6 +1803,9 @@ void ipa_delete_dflt_flt_rules(u32 ipa_ep_idx);
int ipa_enable_data_path(u32 clnt_hdl);
int ipa_disable_data_path(u32 clnt_hdl);
+int ipa2_enable_force_clear(u32 request_id, bool throttle_source,
+ u32 source_pipe_bitmask);
+int ipa2_disable_force_clear(u32 request_id);
int ipa_id_alloc(void *ptr);
void *ipa_id_find(u32 id);
void ipa_id_remove(u32 id);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c
index d88e5a6d3d73..e2ac9bfceed7 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c
@@ -39,6 +39,8 @@
#define QMI_SEND_STATS_REQ_TIMEOUT_MS 5000
#define QMI_SEND_REQ_TIMEOUT_MS 60000
+#define QMI_IPA_FORCE_CLEAR_DATAPATH_TIMEOUT_MS 1000
+
static struct qmi_handle *ipa_svc_handle;
static void ipa_a5_svc_recv_msg(struct work_struct *work);
static DECLARE_DELAYED_WORK(work_recv_msg, ipa_a5_svc_recv_msg);
@@ -583,7 +585,8 @@ int qmi_enable_force_clear_datapath_send(
&req_desc,
req,
sizeof(*req),
- &resp_desc, &resp, sizeof(resp), 0);
+ &resp_desc, &resp, sizeof(resp),
+ QMI_IPA_FORCE_CLEAR_DATAPATH_TIMEOUT_MS);
if (rc < 0) {
IPAWANERR("send req failed %d\n", rc);
return rc;
@@ -628,7 +631,8 @@ int qmi_disable_force_clear_datapath_send(
&req_desc,
req,
sizeof(*req),
- &resp_desc, &resp, sizeof(resp), 0);
+ &resp_desc, &resp, sizeof(resp),
+ QMI_IPA_FORCE_CLEAR_DATAPATH_TIMEOUT_MS);
if (rc < 0) {
IPAWANERR("send req failed %d\n", rc);
return rc;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
index 5bda4cb9ed2b..f60669132865 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
@@ -1404,7 +1404,6 @@ int ipa2_disable_wdi_pipe(u32 clnt_hdl)
union IpaHwWdiCommonChCmdData_t disable;
struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
u32 prod_hdl;
- int i;
if (unlikely(!ipa_ctx)) {
IPAERR("IPA driver was not initialized\n");
@@ -1421,28 +1420,6 @@ int ipa2_disable_wdi_pipe(u32 clnt_hdl)
if (result)
return result;
- /* checking rdy_ring_rp_pa matches the rdy_comp_ring_wp_pa on WDI2.0 */
- if (ipa_ctx->ipa_wdi2) {
- for (i = 0; i < IPA_UC_FINISH_MAX; i++) {
- IPADBG("(%d) rp_value(%u), comp_wp_value(%u)\n",
- i,
- *ipa_ctx->uc_ctx.rdy_ring_rp_va,
- *ipa_ctx->uc_ctx.rdy_comp_ring_wp_va);
- if (*ipa_ctx->uc_ctx.rdy_ring_rp_va !=
- *ipa_ctx->uc_ctx.rdy_comp_ring_wp_va) {
- usleep_range(IPA_UC_WAIT_MIN_SLEEP,
- IPA_UC_WAII_MAX_SLEEP);
- } else {
- break;
- }
- }
- /* In case ipa_uc still haven't processed all
- * pending descriptors, we have to assert
- */
- if (i == IPA_UC_FINISH_MAX)
- BUG();
- }
-
IPADBG("ep=%d\n", clnt_hdl);
ep = &ipa_ctx->ep[clnt_hdl];
@@ -1468,6 +1445,11 @@ int ipa2_disable_wdi_pipe(u32 clnt_hdl)
* holb on IPA Producer pipe
*/
if (IPA_CLIENT_IS_PROD(ep->client)) {
+
+ IPADBG("Stopping PROD channel - hdl=%d clnt=%d\n",
+ clnt_hdl, ep->client);
+
+ /* remove delay on wlan-prod pipe*/
memset(&ep_cfg_ctrl, 0 , sizeof(struct ipa_ep_cfg_ctrl));
ipa2_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl);
@@ -1594,6 +1576,8 @@ int ipa2_suspend_wdi_pipe(u32 clnt_hdl)
struct ipa_ep_context *ep;
union IpaHwWdiCommonChCmdData_t suspend;
struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
+ u32 source_pipe_bitmask = 0;
+ bool disable_force_clear = false;
if (unlikely(!ipa_ctx)) {
IPAERR("IPA driver was not initialized\n");
@@ -1623,6 +1607,31 @@ int ipa2_suspend_wdi_pipe(u32 clnt_hdl)
suspend.params.ipa_pipe_number = clnt_hdl;
if (IPA_CLIENT_IS_PROD(ep->client)) {
+ /*
+ * For WDI 2.0 need to ensure pipe will be empty before suspend
+ * as IPA uC will fail to suspend the pipe otherwise.
+ */
+ if (ipa_ctx->ipa_wdi2) {
+ source_pipe_bitmask = 1 <<
+ ipa_get_ep_mapping(ep->client);
+ result = ipa2_enable_force_clear(clnt_hdl,
+ false, source_pipe_bitmask);
+ if (result) {
+ /*
+ * assuming here modem SSR, AP can remove
+ * the delay in this case
+ */
+ IPAERR("failed to force clear %d\n", result);
+ IPAERR("remove delay from SCND reg\n");
+ memset(&ep_cfg_ctrl, 0,
+ sizeof(struct ipa_ep_cfg_ctrl));
+ ep_cfg_ctrl.ipa_ep_delay = false;
+ ep_cfg_ctrl.ipa_ep_suspend = false;
+ ipa2_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl);
+ } else {
+ disable_force_clear = true;
+ }
+ }
IPADBG("Post suspend event first for IPA Producer\n");
IPADBG("Client: %d clnt_hdl: %d\n", ep->client, clnt_hdl);
result = ipa_uc_send_cmd(suspend.raw32b,
@@ -1667,6 +1676,9 @@ int ipa2_suspend_wdi_pipe(u32 clnt_hdl)
}
}
+ if (disable_force_clear)
+ ipa2_disable_force_clear(clnt_hdl);
+
ipa_ctx->tag_process_before_gating = true;
IPA_ACTIVE_CLIENTS_DEC_EP(ipa2_get_client_mapping(clnt_hdl));
ep->uc_offload_state &= ~IPA_WDI_RESUMED;
diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c
index 35dc3842017b..4039b4312e93 100644
--- a/drivers/power/supply/qcom/battery.c
+++ b/drivers/power/supply/qcom/battery.c
@@ -45,6 +45,7 @@ struct pl_data {
struct votable *fv_votable;
struct votable *pl_disable_votable;
struct votable *pl_awake_votable;
+ struct votable *hvdcp_hw_inov_dis_votable;
struct work_struct status_change_work;
struct work_struct pl_disable_forever_work;
struct delayed_work pl_taper_work;
@@ -96,7 +97,8 @@ static void split_settled(struct pl_data *chip)
* for desired split
*/
- if (chip->pl_mode != POWER_SUPPLY_PARALLEL_USBIN_USBIN)
+ if ((chip->pl_mode != POWER_SUPPLY_PL_USBIN_USBIN)
+ && (chip->pl_mode != POWER_SUPPLY_PL_USBIN_USBIN_EXT))
return;
if (!chip->main_psy)
@@ -262,7 +264,7 @@ static void split_fcc(struct pl_data *chip, int total_ua,
hw_cc_delta_ua = pval.intval;
bcl_ua = INT_MAX;
- if (chip->pl_mode == POWER_SUPPLY_PARALLEL_MID_MID) {
+ if (chip->pl_mode == POWER_SUPPLY_PL_USBMID_USBMID) {
rc = power_supply_get_property(chip->main_psy,
POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, &pval);
if (rc < 0) {
@@ -287,7 +289,15 @@ static void split_fcc(struct pl_data *chip, int total_ua,
slave_limited_ua = min(effective_total_ua, bcl_ua);
*slave_ua = (slave_limited_ua * chip->slave_pct) / 100;
*slave_ua = (*slave_ua * chip->taper_pct) / 100;
- *master_ua = max(0, total_ua - *slave_ua);
+ /*
+ * In USBIN_USBIN configuration with internal rsense parallel
+ * charger's current goes through main charger's BATFET, keep
+ * the main charger's FCC to the votable result.
+ */
+ if (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
+ *master_ua = max(0, total_ua);
+ else
+ *master_ua = max(0, total_ua - *slave_ua);
}
static int pl_fcc_vote_callback(struct votable *votable, void *data,
@@ -316,7 +326,7 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data,
total_fcc_ua = pval.intval;
}
- if (chip->pl_mode == POWER_SUPPLY_PARALLEL_NONE
+ if (chip->pl_mode == POWER_SUPPLY_PL_NONE
|| get_effective_result_locked(chip->pl_disable_votable)) {
pval.intval = total_fcc_ua;
rc = power_supply_set_property(chip->main_psy,
@@ -391,7 +401,7 @@ static int pl_fv_vote_callback(struct votable *votable, void *data,
return rc;
}
- if (chip->pl_mode != POWER_SUPPLY_PARALLEL_NONE) {
+ if (chip->pl_mode != POWER_SUPPLY_PL_NONE) {
pval.intval += PARALLEL_FLOAT_VOLTAGE_DELTA_UV;
rc = power_supply_set_property(chip->pl_psy,
POWER_SUPPLY_PROP_VOLTAGE_MAX, &pval);
@@ -411,6 +421,10 @@ static void pl_disable_forever_work(struct work_struct *work)
/* Disable Parallel charger forever */
vote(chip->pl_disable_votable, PL_HW_ABSENT_VOTER, true, 0);
+
+ /* Re-enable autonomous mode */
+ if (chip->hvdcp_hw_inov_dis_votable)
+ vote(chip->hvdcp_hw_inov_dis_votable, PL_VOTER, false, 0);
}
static int pl_disable_vote_callback(struct votable *votable,
@@ -451,7 +465,8 @@ static int pl_disable_vote_callback(struct votable *votable,
pr_err("Couldn't change slave suspend state rc=%d\n",
rc);
- if (chip->pl_mode == POWER_SUPPLY_PARALLEL_USBIN_USBIN)
+ if ((chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
+ || (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT))
split_settled(chip);
/*
* we could have been enabled while in taper mode,
@@ -469,7 +484,8 @@ static int pl_disable_vote_callback(struct votable *votable,
}
}
} else {
- if (chip->pl_mode == POWER_SUPPLY_PARALLEL_USBIN_USBIN)
+ if ((chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
+ || (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT))
split_settled(chip);
/* pl_psy may be NULL while in the disable branch */
@@ -552,6 +568,21 @@ static bool is_parallel_available(struct pl_data *chip)
* pl_psy is present and valid.
*/
chip->pl_mode = pval.intval;
+
+ /* Disable autonomous votage increments for USBIN-USBIN */
+ if ((chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
+ || (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT)) {
+ if (!chip->hvdcp_hw_inov_dis_votable)
+ chip->hvdcp_hw_inov_dis_votable =
+ find_votable("HVDCP_HW_INOV_DIS");
+ if (chip->hvdcp_hw_inov_dis_votable)
+ /* Read current pulse count */
+ vote(chip->hvdcp_hw_inov_dis_votable, PL_VOTER,
+ true, 0);
+ else
+ return false;
+ }
+
vote(chip->pl_disable_votable, PARALLEL_PSY_VOTER, false, 0);
return true;
@@ -610,7 +641,8 @@ static void handle_settled_aicl_split(struct pl_data *chip)
int rc;
if (!get_effective_result(chip->pl_disable_votable)
- && chip->pl_mode == POWER_SUPPLY_PARALLEL_USBIN_USBIN) {
+ && (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN
+ || chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT)) {
/*
* call aicl split only when USBIN_USBIN and enabled
* and if aicl changed
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 773e8b00c1c0..7e5b239cea96 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -848,6 +848,8 @@ static enum power_supply_property smb2_batt_props[] = {
POWER_SUPPLY_PROP_PARALLEL_DISABLE,
POWER_SUPPLY_PROP_SET_SHIP_MODE,
POWER_SUPPLY_PROP_DIE_HEALTH,
+ POWER_SUPPLY_PROP_RERUN_AICL,
+ POWER_SUPPLY_PROP_DP_DM,
};
static int smb2_batt_get_prop(struct power_supply *psy,
@@ -933,6 +935,12 @@ static int smb2_batt_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_DIE_HEALTH:
rc = smblib_get_prop_die_health(chg, val);
break;
+ case POWER_SUPPLY_PROP_DP_DM:
+ val->intval = chg->pulse_cnt;
+ break;
+ case POWER_SUPPLY_PROP_RERUN_AICL:
+ val->intval = 0;
+ break;
default:
pr_err("batt power supply prop %d not supported\n", psp);
return -EINVAL;
@@ -986,6 +994,12 @@ static int smb2_batt_set_prop(struct power_supply *psy,
break;
rc = smblib_set_prop_ship_mode(chg, val);
break;
+ case POWER_SUPPLY_PROP_RERUN_AICL:
+ rc = smblib_rerun_aicl(chg);
+ break;
+ case POWER_SUPPLY_PROP_DP_DM:
+ rc = smblib_dp_dm(chg, val->intval);
+ break;
default:
rc = -EINVAL;
}
@@ -1001,6 +1015,8 @@ static int smb2_batt_prop_is_writeable(struct power_supply *psy,
case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
case POWER_SUPPLY_PROP_CAPACITY:
case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
+ case POWER_SUPPLY_PROP_DP_DM:
+ case POWER_SUPPLY_PROP_RERUN_AICL:
return 1;
default:
break;
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 47228664e03f..ce2e077c4f07 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -58,6 +58,12 @@ int smblib_read(struct smb_charger *chg, u16 addr, u8 *val)
return rc;
}
+int smblib_multibyte_read(struct smb_charger *chg, u16 addr, u8 *val,
+ int count)
+{
+ return regmap_bulk_read(chg->regmap, addr, val, count);
+}
+
int smblib_masked_write(struct smb_charger *chg, u16 addr, u8 mask, u8 val)
{
int rc = 0;
@@ -652,6 +658,8 @@ static void smblib_uusb_removal(struct smb_charger *chg)
chg->voltage_min_uv = MICRO_5V;
chg->voltage_max_uv = MICRO_5V;
+ chg->usb_icl_delta_ua = 0;
+ chg->pulse_cnt = 0;
/* clear USB ICL vote for USB_PSY_VOTER */
rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
@@ -741,6 +749,40 @@ int smblib_rerun_apsd_if_required(struct smb_charger *chg)
return 0;
}
+static int smblib_get_pulse_cnt(struct smb_charger *chg, int *count)
+{
+ int rc;
+ u8 val[2];
+
+ switch (chg->smb_version) {
+ case PMI8998_SUBTYPE:
+ rc = smblib_read(chg, QC_PULSE_COUNT_STATUS_REG, val);
+ if (rc) {
+ pr_err("failed to read QC_PULSE_COUNT_STATUS_REG rc=%d\n",
+ rc);
+ return rc;
+ }
+ *count = val[0] & QC_PULSE_COUNT_MASK;
+ break;
+ case PM660_SUBTYPE:
+ rc = smblib_multibyte_read(chg,
+ QC_PULSE_COUNT_STATUS_1_REG, val, 2);
+ if (rc) {
+ pr_err("failed to read QC_PULSE_COUNT_STATUS_1_REG rc=%d\n",
+ rc);
+ return rc;
+ }
+ *count = (val[1] << 8) | val[0];
+ break;
+ default:
+ smblib_dbg(chg, PR_PARALLEL, "unknown SMB chip %d\n",
+ chg->smb_version);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/*********************
* VOTABLE CALLBACKS *
*********************/
@@ -975,8 +1017,10 @@ static int smblib_hvdcp_enable_vote_callback(struct votable *votable,
{
struct smb_charger *chg = data;
int rc;
- u8 val = HVDCP_AUTH_ALG_EN_CFG_BIT
- | HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT | HVDCP_EN_BIT;
+ u8 val = HVDCP_AUTH_ALG_EN_CFG_BIT | HVDCP_EN_BIT;
+
+ /* vote to enable/disable HW autonomous INOV */
+ vote(chg->hvdcp_hw_inov_dis_votable, client, !hvdcp_enable, 0);
/*
* Disable the autonomous bit and auth bit for disabling hvdcp.
@@ -987,9 +1031,7 @@ static int smblib_hvdcp_enable_vote_callback(struct votable *votable,
val = HVDCP_EN_BIT;
rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
- HVDCP_EN_BIT
- | HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT
- | HVDCP_AUTH_ALG_EN_CFG_BIT,
+ HVDCP_EN_BIT | HVDCP_AUTH_ALG_EN_CFG_BIT,
val);
if (rc < 0) {
smblib_err(chg, "Couldn't %s hvdcp rc=%d\n",
@@ -1058,6 +1100,37 @@ static int smblib_apsd_disable_vote_callback(struct votable *votable,
return 0;
}
+static int smblib_hvdcp_hw_inov_dis_vote_callback(struct votable *votable,
+ void *data, int disable, const char *client)
+{
+ struct smb_charger *chg = data;
+ int rc;
+
+ if (disable) {
+ /*
+ * the pulse count register get zeroed when autonomous mode is
+ * disabled. Track that in variables before disabling
+ */
+ rc = smblib_get_pulse_cnt(chg, &chg->pulse_cnt);
+ if (rc < 0) {
+ pr_err("failed to read QC_PULSE_COUNT_STATUS_REG rc=%d\n",
+ rc);
+ return rc;
+ }
+ }
+
+ rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
+ HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT,
+ disable ? 0 : HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't %s hvdcp rc=%d\n",
+ disable ? "disable" : "enable", rc);
+ return rc;
+ }
+
+ return rc;
+}
+
/*******************
* VCONN REGULATOR *
* *****************/
@@ -1645,6 +1718,98 @@ int smblib_set_prop_system_temp_level(struct smb_charger *chg,
return 0;
}
+int smblib_rerun_aicl(struct smb_charger *chg)
+{
+ int rc = 0;
+ u8 val;
+
+ /*
+ * Use restart_AICL instead of trigger_AICL as it runs the
+ * complete AICL instead of starting from the last settled value.
+ *
+ * 8998 only supports trigger_AICL return error for 8998
+ */
+ switch (chg->smb_version) {
+ case PMI8998_SUBTYPE:
+ smblib_dbg(chg, PR_PARALLEL, "AICL rerun not supported\n");
+ return -EINVAL;
+ case PM660_SUBTYPE:
+ val = RESTART_AICL_BIT;
+ break;
+ default:
+ smblib_dbg(chg, PR_PARALLEL, "unknown SMB chip %d\n",
+ chg->smb_version);
+ return -EINVAL;
+ }
+ rc = smblib_masked_write(chg, CMD_HVDCP_2_REG, val, val);
+ if (rc < 0)
+ smblib_err(chg, "Couldn't write to CMD_HVDCP_2_REG rc=%d\n",
+ rc);
+
+ return rc;
+}
+
+static int smblib_dp_pulse(struct smb_charger *chg)
+{
+ int rc;
+
+ /* QC 3.0 increment */
+ rc = smblib_masked_write(chg, CMD_HVDCP_2_REG, SINGLE_INCREMENT_BIT,
+ SINGLE_INCREMENT_BIT);
+ if (rc < 0)
+ smblib_err(chg, "Couldn't write to CMD_HVDCP_2_REG rc=%d\n",
+ rc);
+
+ return rc;
+}
+
+static int smblib_dm_pulse(struct smb_charger *chg)
+{
+ int rc;
+
+ /* QC 3.0 decrement */
+ rc = smblib_masked_write(chg, CMD_HVDCP_2_REG, SINGLE_DECREMENT_BIT,
+ SINGLE_DECREMENT_BIT);
+ if (rc < 0)
+ smblib_err(chg, "Couldn't write to CMD_HVDCP_2_REG rc=%d\n",
+ rc);
+
+ return rc;
+}
+
+int smblib_dp_dm(struct smb_charger *chg, int val)
+{
+ int target_icl_ua, rc = 0;
+
+ switch (val) {
+ case POWER_SUPPLY_DP_DM_DP_PULSE:
+ rc = smblib_dp_pulse(chg);
+ if (!rc)
+ chg->pulse_cnt++;
+ smblib_dbg(chg, PR_PARALLEL, "DP_DM_DP_PULSE rc=%d cnt=%d\n",
+ rc, chg->pulse_cnt);
+ break;
+ case POWER_SUPPLY_DP_DM_DM_PULSE:
+ rc = smblib_dm_pulse(chg);
+ if (!rc && chg->pulse_cnt)
+ chg->pulse_cnt--;
+ smblib_dbg(chg, PR_PARALLEL, "DP_DM_DM_PULSE rc=%d cnt=%d\n",
+ rc, chg->pulse_cnt);
+ break;
+ case POWER_SUPPLY_DP_DM_ICL_DOWN:
+ chg->usb_icl_delta_ua -= 100000;
+ target_icl_ua = get_effective_result(chg->usb_icl_votable);
+ vote(chg->usb_icl_votable, SW_QC3_VOTER, true,
+ target_icl_ua + chg->usb_icl_delta_ua);
+ break;
+ case POWER_SUPPLY_DP_DM_ICL_UP:
+ default:
+ break;
+ }
+
+ return rc;
+}
+
/*******************
* DC PSY GETTERS *
*******************/
@@ -2915,26 +3080,38 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
}
#define USB_WEAK_INPUT_UA 1400000
+#define ICL_CHANGE_DELAY_MS 1000
irqreturn_t smblib_handle_icl_change(int irq, void *data)
{
+ u8 stat;
+ int rc, settled_ua, delay = ICL_CHANGE_DELAY_MS;
struct smb_irq_data *irq_data = data;
struct smb_charger *chg = irq_data->parent_data;
- int rc, settled_ua;
-
- rc = smblib_get_charge_param(chg, &chg->param.icl_stat, &settled_ua);
- if (rc < 0) {
- smblib_err(chg, "Couldn't get ICL status rc=%d\n", rc);
- return IRQ_HANDLED;
- }
if (chg->mode == PARALLEL_MASTER) {
- power_supply_changed(chg->usb_main_psy);
- vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER,
- settled_ua >= USB_WEAK_INPUT_UA, 0);
+ rc = smblib_read(chg, AICL_STATUS_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read AICL_STATUS rc=%d\n",
+ rc);
+ return IRQ_HANDLED;
+ }
+
+ rc = smblib_get_charge_param(chg, &chg->param.icl_stat,
+ &settled_ua);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get ICL status rc=%d\n", rc);
+ return IRQ_HANDLED;
+ }
+
+ /* If AICL settled then schedule work now */
+ if ((settled_ua == get_effective_result(chg->usb_icl_votable))
+ || (stat & AICL_DONE_BIT))
+ delay = 0;
+
+ schedule_delayed_work(&chg->icl_change_work,
+ msecs_to_jiffies(delay));
}
- smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s icl_settled=%d\n",
- irq_data->name, settled_ua);
return IRQ_HANDLED;
}
@@ -3279,6 +3456,8 @@ static void smblib_handle_typec_removal(struct smb_charger *chg)
chg->vconn_attempts = 0;
chg->otg_attempts = 0;
+ chg->pulse_cnt = 0;
+ chg->usb_icl_delta_ua = 0;
chg->usb_ever_removed = true;
@@ -3801,6 +3980,25 @@ static void smblib_otg_ss_done_work(struct work_struct *work)
mutex_unlock(&chg->otg_oc_lock);
}
+static void smblib_icl_change_work(struct work_struct *work)
+{
+ struct smb_charger *chg = container_of(work, struct smb_charger,
+ icl_change_work.work);
+ int rc, settled_ua;
+
+ rc = smblib_get_charge_param(chg, &chg->param.icl_stat, &settled_ua);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get ICL status rc=%d\n", rc);
+ return;
+ }
+
+ power_supply_changed(chg->usb_main_psy);
+ vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER,
+ settled_ua >= USB_WEAK_INPUT_UA, 0);
+
+ smblib_dbg(chg, PR_INTERRUPT, "icl_settled=%d\n", settled_ua);
+}
+
static int smblib_create_votables(struct smb_charger *chg)
{
int rc = 0;
@@ -3917,6 +4115,15 @@ static int smblib_create_votables(struct smb_charger *chg)
return rc;
}
+ chg->hvdcp_hw_inov_dis_votable = create_votable("HVDCP_HW_INOV_DIS",
+ VOTE_SET_ANY,
+ smblib_hvdcp_hw_inov_dis_vote_callback,
+ chg);
+ if (IS_ERR(chg->hvdcp_hw_inov_dis_votable)) {
+ rc = PTR_ERR(chg->hvdcp_hw_inov_dis_votable);
+ return rc;
+ }
+
return rc;
}
@@ -3940,6 +4147,8 @@ static void smblib_destroy_votables(struct smb_charger *chg)
destroy_votable(chg->pl_enable_votable_indirect);
if (chg->apsd_disable_votable)
destroy_votable(chg->apsd_disable_votable);
+ if (chg->hvdcp_hw_inov_dis_votable)
+ destroy_votable(chg->hvdcp_hw_inov_dis_votable);
}
static void smblib_iio_deinit(struct smb_charger *chg)
@@ -3970,6 +4179,7 @@ int smblib_init(struct smb_charger *chg)
INIT_WORK(&chg->otg_oc_work, smblib_otg_oc_work);
INIT_WORK(&chg->vconn_oc_work, smblib_vconn_oc_work);
INIT_DELAYED_WORK(&chg->otg_ss_done_work, smblib_otg_ss_done_work);
+ INIT_DELAYED_WORK(&chg->icl_change_work, smblib_icl_change_work);
chg->fake_capacity = -EINVAL;
switch (chg->mode) {
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index bf2d863933ae..fa6fd3eb310d 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -56,6 +56,7 @@ enum print_reason {
#define PD_SUSPEND_SUPPORTED_VOTER "PD_SUSPEND_SUPPORTED_VOTER"
#define PL_DELAY_HVDCP_VOTER "PL_DELAY_HVDCP_VOTER"
#define CTM_VOTER "CTM_VOTER"
+#define SW_QC3_VOTER "SW_QC3_VOTER"
#define VCONN_MAX_ATTEMPTS 3
#define OTG_MAX_ATTEMPTS 3
@@ -202,6 +203,7 @@ struct smb_iio {
struct iio_channel *usbin_i_chan;
struct iio_channel *usbin_v_chan;
struct iio_channel *batt_i_chan;
+ struct iio_channel *connector_temp_chan;
struct iio_channel *connector_temp_thr1_chan;
struct iio_channel *connector_temp_thr2_chan;
struct iio_channel *connector_temp_thr3_chan;
@@ -267,6 +269,7 @@ struct smb_charger {
struct votable *hvdcp_disable_votable_indirect;
struct votable *hvdcp_enable_votable;
struct votable *apsd_disable_votable;
+ struct votable *hvdcp_hw_inov_dis_votable;
/* work */
struct work_struct bms_update_work;
@@ -278,6 +281,7 @@ struct smb_charger {
struct work_struct otg_oc_work;
struct work_struct vconn_oc_work;
struct delayed_work otg_ss_done_work;
+ struct delayed_work icl_change_work;
/* cached status */
int voltage_min_uv;
@@ -315,6 +319,8 @@ struct smb_charger {
/* qnovo */
int qnovo_fcc_ua;
int qnovo_fv_uv;
+ int usb_icl_delta_ua;
+ int pulse_cnt;
};
int smblib_read(struct smb_charger *chg, u16 addr, u8 *val);
@@ -472,6 +478,8 @@ int smblib_get_prop_fcc_delta(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_icl_override(struct smb_charger *chg, bool override);
int smblib_set_icl_reduction(struct smb_charger *chg, int reduction_ua);
+int smblib_dp_dm(struct smb_charger *chg, int val);
+int smblib_rerun_aicl(struct smb_charger *chg);
int smblib_init(struct smb_charger *chg);
int smblib_deinit(struct smb_charger *chg);
diff --git a/drivers/power/supply/qcom/smb-reg.h b/drivers/power/supply/qcom/smb-reg.h
index e005a27e8dd9..54b6b38d134b 100644
--- a/drivers/power/supply/qcom/smb-reg.h
+++ b/drivers/power/supply/qcom/smb-reg.h
@@ -535,6 +535,8 @@ enum {
#define USBIN_LT_3P6V_RT_STS_BIT BIT(1)
#define USBIN_COLLAPSE_RT_STS_BIT BIT(0)
+#define QC_PULSE_COUNT_STATUS_1_REG (USBIN_BASE + 0x30)
+
#define USBIN_CMD_IL_REG (USBIN_BASE + 0x40)
#define BAT_2_SYS_FET_DIS_BIT BIT(1)
#define USBIN_SUSPEND_BIT BIT(0)
@@ -544,6 +546,7 @@ enum {
#define APSD_RERUN_BIT BIT(0)
#define CMD_HVDCP_2_REG (USBIN_BASE + 0x43)
+#define RESTART_AICL_BIT BIT(7)
#define TRIGGER_AICL_BIT BIT(6)
#define FORCE_12V_BIT BIT(5)
#define FORCE_9V_BIT BIT(4)
diff --git a/drivers/power/supply/qcom/smb1351-charger.c b/drivers/power/supply/qcom/smb1351-charger.c
index d0cf37b0613a..8467d167512f 100644
--- a/drivers/power/supply/qcom/smb1351-charger.c
+++ b/drivers/power/supply/qcom/smb1351-charger.c
@@ -460,6 +460,7 @@ struct smb1351_charger {
int workaround_flags;
int parallel_pin_polarity_setting;
+ int parallel_mode;
bool parallel_charger;
bool parallel_charger_suspended;
bool bms_controlled_charging;
@@ -1699,7 +1700,7 @@ static int smb1351_parallel_get_property(struct power_supply *psy,
val->intval = 0;
break;
case POWER_SUPPLY_PROP_PARALLEL_MODE:
- val->intval = POWER_SUPPLY_PARALLEL_USBIN_USBIN;
+ val->intval = chip->parallel_mode;
break;
default:
return -EINVAL;
@@ -3191,6 +3192,12 @@ static int smb1351_parallel_charger_probe(struct i2c_client *client,
chip->parallel_pin_polarity_setting ?
EN_BY_PIN_HIGH_ENABLE : EN_BY_PIN_LOW_ENABLE;
+ if (of_property_read_bool(node,
+ "qcom,parallel-external-current-sense"))
+ chip->parallel_mode = POWER_SUPPLY_PL_USBIN_USBIN_EXT;
+ else
+ chip->parallel_mode = POWER_SUPPLY_PL_USBIN_USBIN;
+
i2c_set_clientdata(client, chip);
chip->parallel_psy_d.name = "parallel";
diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c
index 4180edc89a4c..fe1aced4f5c6 100644
--- a/drivers/power/supply/qcom/smb138x-charger.c
+++ b/drivers/power/supply/qcom/smb138x-charger.c
@@ -430,6 +430,57 @@ static int smb138x_init_batt_psy(struct smb138x *chip)
* PARALLEL PSY REGISTRATION *
*****************************/
+static int smb138x_get_prop_connector_health(struct smb138x *chip)
+{
+ struct smb_charger *chg = &chip->chg;
+ int rc, lb_mdegc, ub_mdegc, rst_mdegc, connector_mdegc;
+
+ if (!chg->iio.connector_temp_chan ||
+ PTR_ERR(chg->iio.connector_temp_chan) == -EPROBE_DEFER)
+ chg->iio.connector_temp_chan = iio_channel_get(chg->dev,
+ "connector_temp");
+
+ if (IS_ERR(chg->iio.connector_temp_chan))
+ return POWER_SUPPLY_HEALTH_UNKNOWN;
+
+ rc = iio_read_channel_processed(chg->iio.connector_temp_thr1_chan,
+ &lb_mdegc);
+ if (rc < 0) {
+ pr_err("Couldn't read connector lower bound rc=%d\n", rc);
+ return POWER_SUPPLY_HEALTH_UNKNOWN;
+ }
+
+ rc = iio_read_channel_processed(chg->iio.connector_temp_thr2_chan,
+ &ub_mdegc);
+ if (rc < 0) {
+ pr_err("Couldn't read connector upper bound rc=%d\n", rc);
+ return POWER_SUPPLY_HEALTH_UNKNOWN;
+ }
+
+ rc = iio_read_channel_processed(chg->iio.connector_temp_thr3_chan,
+ &rst_mdegc);
+ if (rc < 0) {
+ pr_err("Couldn't read connector reset bound rc=%d\n", rc);
+ return POWER_SUPPLY_HEALTH_UNKNOWN;
+ }
+
+ rc = iio_read_channel_processed(chg->iio.connector_temp_chan,
+ &connector_mdegc);
+ if (rc < 0) {
+ pr_err("Couldn't read connector temperature rc=%d\n", rc);
+ return POWER_SUPPLY_HEALTH_UNKNOWN;
+ }
+
+ if (connector_mdegc < lb_mdegc)
+ return POWER_SUPPLY_HEALTH_COOL;
+ else if (connector_mdegc < ub_mdegc)
+ return POWER_SUPPLY_HEALTH_WARM;
+ else if (connector_mdegc < rst_mdegc)
+ return POWER_SUPPLY_HEALTH_HOT;
+
+ return POWER_SUPPLY_HEALTH_OVERHEAT;
+}
+
static enum power_supply_property smb138x_parallel_props[] = {
POWER_SUPPLY_PROP_CHARGE_TYPE,
POWER_SUPPLY_PROP_CHARGING_ENABLED,
@@ -493,10 +544,10 @@ static int smb138x_parallel_get_prop(struct power_supply *psy,
val->strval = "smb138x";
break;
case POWER_SUPPLY_PROP_PARALLEL_MODE:
- val->intval = POWER_SUPPLY_PARALLEL_MID_MID;
+ val->intval = POWER_SUPPLY_PL_USBMID_USBMID;
break;
case POWER_SUPPLY_PROP_CONNECTOR_HEALTH:
- rc = smblib_get_prop_die_health(chg, val);
+ val->intval = smb138x_get_prop_connector_health(chip);
break;
default:
pr_err("parallel power supply get prop %d not supported\n",
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 7369478a8c5d..bc00a7e9572f 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -35,6 +35,9 @@
#include "ufs-qcom-debugfs.h"
#include <linux/clk/msm-clk.h>
+#define MAX_PROP_SIZE 32
+#define VDDP_REF_CLK_MIN_UV 1200000
+#define VDDP_REF_CLK_MAX_UV 1200000
/* TODO: further tuning for this parameter may be required */
#define UFS_QCOM_PM_QOS_UNVOTE_TIMEOUT_US (10000) /* microseconds */
@@ -709,40 +712,105 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba *hba,
return err;
}
-static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
+
+static int ufs_qcom_config_vreg(struct device *dev,
+ struct ufs_vreg *vreg, bool on)
{
- struct ufs_qcom_host *host = ufshcd_get_variant(hba);
- struct phy *phy = host->generic_phy;
int ret = 0;
+ struct regulator *reg;
+ int min_uV, uA_load;
- if (ufs_qcom_is_link_off(hba)) {
- /*
- * Disable the tx/rx lane symbol clocks before PHY is
- * powered down as the PLL source should be disabled
- * after downstream clocks are disabled.
- */
- ufs_qcom_disable_lane_clks(host);
- phy_power_off(phy);
- ret = ufs_qcom_ice_suspend(host);
+ if (!vreg) {
+ WARN_ON(1);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ reg = vreg->reg;
+ if (regulator_count_voltages(reg) > 0) {
+ min_uV = on ? vreg->min_uV : 0;
+ ret = regulator_set_voltage(reg, min_uV, vreg->max_uV);
+ if (ret) {
+ dev_err(dev, "%s: %s set voltage failed, err=%d\n",
+ __func__, vreg->name, ret);
+ goto out;
+ }
+
+ uA_load = on ? vreg->max_uA : 0;
+ ret = regulator_set_load(vreg->reg, uA_load);
if (ret)
- dev_err(hba->dev, "%s: failed ufs_qcom_ice_suspend %d\n",
- __func__, ret);
+ goto out;
+ }
+out:
+ return ret;
+}
+
+static int ufs_qcom_enable_vreg(struct device *dev, struct ufs_vreg *vreg)
+{
+ int ret = 0;
+
+ if (vreg->enabled)
+ return ret;
- /* Assert PHY soft reset */
- ufs_qcom_assert_reset(hba);
+ ret = ufs_qcom_config_vreg(dev, vreg, true);
+ if (ret)
+ goto out;
+
+ ret = regulator_enable(vreg->reg);
+ if (ret)
+ goto out;
+
+ vreg->enabled = true;
+out:
+ return ret;
+}
+
+static int ufs_qcom_disable_vreg(struct device *dev, struct ufs_vreg *vreg)
+{
+ int ret = 0;
+
+ if (!vreg->enabled)
+ return ret;
+
+ ret = regulator_disable(vreg->reg);
+ if (ret)
+ goto out;
+
+ ret = ufs_qcom_config_vreg(dev, vreg, false);
+ if (ret)
goto out;
- }
+
+ vreg->enabled = false;
+out:
+ return ret;
+}
+
+static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
+{
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ struct phy *phy = host->generic_phy;
+ int ret = 0;
/*
- * If UniPro link is not active, PHY ref_clk, main PHY analog power
- * rail and low noise analog power rail for PLL can be switched off.
+ * If UniPro link is not active or OFF, PHY ref_clk, main PHY analog
+ * power rail and low noise analog power rail for PLL can be
+ * switched off.
*/
if (!ufs_qcom_is_link_active(hba)) {
ufs_qcom_disable_lane_clks(host);
phy_power_off(phy);
+
+ if (host->vddp_ref_clk && ufs_qcom_is_link_off(hba))
+ ret = ufs_qcom_disable_vreg(hba->dev,
+ host->vddp_ref_clk);
ufs_qcom_ice_suspend(host);
- }
+ if (ufs_qcom_is_link_off(hba)) {
+ /* Assert PHY soft reset */
+ ufs_qcom_assert_reset(hba);
+ goto out;
+ }
+ }
/* Unvote PM QoS */
ufs_qcom_pm_qos_suspend(host);
@@ -763,6 +831,11 @@ static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
goto out;
}
+ if (host->vddp_ref_clk && (hba->rpm_lvl > UFS_PM_LVL_3 ||
+ hba->spm_lvl > UFS_PM_LVL_3))
+ ufs_qcom_enable_vreg(hba->dev,
+ host->vddp_ref_clk);
+
err = ufs_qcom_enable_lane_clks(host);
if (err)
goto out;
@@ -1951,6 +2024,57 @@ static void ufs_qcom_parse_lpm(struct ufs_qcom_host *host)
pr_info("%s: will disable all LPM modes\n", __func__);
}
+static int ufs_qcom_parse_reg_info(struct ufs_qcom_host *host, char *name,
+ struct ufs_vreg **out_vreg)
+{
+ int ret = 0;
+ char prop_name[MAX_PROP_SIZE];
+ struct ufs_vreg *vreg = NULL;
+ struct device *dev = host->hba->dev;
+ struct device_node *np = dev->of_node;
+
+ if (!np) {
+ dev_err(dev, "%s: non DT initialization\n", __func__);
+ goto out;
+ }
+
+ snprintf(prop_name, MAX_PROP_SIZE, "%s-supply", name);
+ if (!of_parse_phandle(np, prop_name, 0)) {
+ dev_info(dev, "%s: Unable to find %s regulator, assuming enabled\n",
+ __func__, prop_name);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL);
+ if (!vreg)
+ return -ENOMEM;
+
+ vreg->name = name;
+
+ snprintf(prop_name, MAX_PROP_SIZE, "%s-max-microamp", name);
+ ret = of_property_read_u32(np, prop_name, &vreg->max_uA);
+ if (ret) {
+ dev_err(dev, "%s: unable to find %s err %d\n",
+ __func__, prop_name, ret);
+ goto out;
+ }
+
+ vreg->reg = devm_regulator_get(dev, vreg->name);
+ if (IS_ERR(vreg->reg)) {
+ ret = PTR_ERR(vreg->reg);
+ dev_err(dev, "%s: %s get failed, err=%d\n",
+ __func__, vreg->name, ret);
+ }
+ vreg->min_uV = VDDP_REF_CLK_MIN_UV;
+ vreg->max_uV = VDDP_REF_CLK_MAX_UV;
+
+out:
+ if (!ret)
+ *out_vreg = vreg;
+ return ret;
+}
+
/**
* ufs_qcom_init - bind phy with controller
* @hba: host controller instance
@@ -2068,14 +2192,24 @@ static int ufs_qcom_init(struct ufs_hba *hba)
ufs_qcom_phy_save_controller_version(host->generic_phy,
host->hw_ver.major, host->hw_ver.minor, host->hw_ver.step);
+ err = ufs_qcom_parse_reg_info(host, "qcom,vddp-ref-clk",
+ &host->vddp_ref_clk);
phy_init(host->generic_phy);
err = phy_power_on(host->generic_phy);
if (err)
goto out_unregister_bus;
+ if (host->vddp_ref_clk) {
+ err = ufs_qcom_enable_vreg(dev, host->vddp_ref_clk);
+ if (err) {
+ dev_err(dev, "%s: failed enabling ref clk supply: %d\n",
+ __func__, err);
+ goto out_disable_phy;
+ }
+ }
err = ufs_qcom_init_lane_clks(host);
if (err)
- goto out_disable_phy;
+ goto out_disable_vddp;
ufs_qcom_parse_lpm(host);
if (host->disable_lpm)
@@ -2100,6 +2234,9 @@ static int ufs_qcom_init(struct ufs_hba *hba)
goto out;
+out_disable_vddp:
+ if (host->vddp_ref_clk)
+ ufs_qcom_disable_vreg(dev, host->vddp_ref_clk);
out_disable_phy:
phy_power_off(host->generic_phy);
out_unregister_bus:
diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h
index 74d8a7a30ad6..12154b268132 100644
--- a/drivers/scsi/ufs/ufs-qcom.h
+++ b/drivers/scsi/ufs/ufs-qcom.h
@@ -373,6 +373,7 @@ struct ufs_qcom_host {
spinlock_t ice_work_lock;
struct work_struct ice_cfg_work;
struct request *req_pending;
+ struct ufs_vreg *vddp_ref_clk;
};
static inline u32
diff --git a/drivers/soc/qcom/qdsp6v2/audio_notifier.c b/drivers/soc/qcom/qdsp6v2/audio_notifier.c
index 47adc3bb3f40..b120883afbb0 100644
--- a/drivers/soc/qcom/qdsp6v2/audio_notifier.c
+++ b/drivers/soc/qcom/qdsp6v2/audio_notifier.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, 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
@@ -394,8 +394,8 @@ static void audio_notifer_reg_all_clients(void)
int ret;
list_for_each_safe(ptr, next, &client_list) {
- client_data = list_entry(ptr,
- struct client_data, list);
+ client_data = list_entry(ptr, struct client_data, list);
+
ret = audio_notifer_reg_client(client_data);
if (IS_ERR_VALUE(ret))
pr_err("%s: audio_notifer_reg_client failed for client %s, ret %d\n",
@@ -518,9 +518,8 @@ int audio_notifier_deregister(char *client_name)
goto done;
}
mutex_lock(&notifier_mutex);
- list_for_each_safe(ptr, next, &client_data->list) {
- client_data = list_entry(ptr, struct client_data,
- list);
+ list_for_each_safe(ptr, next, &client_list) {
+ client_data = list_entry(ptr, struct client_data, list);
if (!strcmp(client_name, client_data->client_name)) {
ret2 = audio_notifer_dereg_client(client_data);
if (ret2 < 0) {
diff --git a/drivers/soc/qcom/rpm_rail_stats.c b/drivers/soc/qcom/rpm_rail_stats.c
index d80a9fc5146a..9ef96dc54eb6 100644
--- a/drivers/soc/qcom/rpm_rail_stats.c
+++ b/drivers/soc/qcom/rpm_rail_stats.c
@@ -27,7 +27,7 @@
#include "rpm_stats.h"
-#define RPM_RAIL_BUF_LEN 600
+#define RPM_RAIL_BUF_LEN 1300
#define SNPRINTF(buf, size, format, ...) \
{ \
@@ -118,7 +118,7 @@ static int msm_rpm_rail_type_copy(void __iomem **base, char **buf, int count)
rail[NAMELEN - 1] = '\0';
memcpy(rail, &rt.rail, NAMELEN - 1);
SNPRINTF(*buf, count,
- "\trail:%-2s num_corners:%-2u current_corner:%-2u last_entered:%-8u\n",
+ "\trail:%-2s \tnum_corners:%-2u current_corner:%-2u last_entered:%-8u\n",
rail, rt.num_corners, rt.current_corner, rt.last_entered);
*base += sizeof(rt);
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index 7244dc9419f3..81ce22e91883 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -889,7 +889,7 @@ static int get_ether_addr_str(u8 dev_addr[ETH_ALEN], char *str, int len)
if (len < 18)
return -EINVAL;
- snprintf(str, len, "%pKM", dev_addr);
+ snprintf(str, len, "%pM", dev_addr);
return 18;
}
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 087cd9fecfe9..ea278781440c 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -1931,6 +1931,11 @@ static void usbpd_sm(struct work_struct *w)
case PE_SNK_SELECT_CAPABILITY:
if (IS_CTRL(rx_msg, MSG_ACCEPT)) {
+ u32 pdo = pd->received_pdos[pd->requested_pdo - 1];
+ bool same_pps = (pd->selected_pdo == pd->requested_pdo)
+ && (PD_SRC_PDO_TYPE(pdo) ==
+ PD_SRC_PDO_TYPE_AUGMENTED);
+
usbpd_set_state(pd, PE_SNK_TRANSITION_SINK);
/* prepare for voltage increase/decrease */
@@ -1942,11 +1947,12 @@ static void usbpd_sm(struct work_struct *w)
&val);
/*
- * if we are changing voltages, we must lower input
- * current to pSnkStdby (2.5W). Calculate it and set
- * PD_CURRENT_MAX accordingly.
+ * if changing voltages (not within the same PPS PDO),
+ * we must lower input current to pSnkStdby (2.5W).
+ * Calculate it and set PD_CURRENT_MAX accordingly.
*/
- if (pd->requested_voltage != pd->current_voltage) {
+ if (!same_pps &&
+ pd->requested_voltage != pd->current_voltage) {
int mv = max(pd->requested_voltage,
pd->current_voltage) / 1000;
val.intval = (2500000 / mv) * 1000;
diff --git a/drivers/usb/phy/phy-msm-qusb.c b/drivers/usb/phy/phy-msm-qusb.c
index 6430e419fc9c..5867c6c204c9 100644
--- a/drivers/usb/phy/phy-msm-qusb.c
+++ b/drivers/usb/phy/phy-msm-qusb.c
@@ -72,6 +72,7 @@
#define QUSB2PHY_PORT_TUNE2 0x84
#define QUSB2PHY_PORT_TUNE3 0x88
#define QUSB2PHY_PORT_TUNE4 0x8C
+#define QUSB2PHY_PORT_TUNE5 0x90
/* In case Efuse register shows zero, use this value */
#define TUNE2_DEFAULT_HIGH_NIBBLE 0xB
@@ -102,10 +103,27 @@
#define QUSB2PHY_REFCLK_ENABLE BIT(0)
+unsigned int tune1;
+module_param(tune1, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(tune1, "QUSB PHY TUNE1");
+
unsigned int tune2;
module_param(tune2, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(tune2, "QUSB PHY TUNE2");
+unsigned int tune3;
+module_param(tune3, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(tune3, "QUSB PHY TUNE3");
+
+unsigned int tune4;
+module_param(tune4, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(tune4, "QUSB PHY TUNE4");
+
+unsigned int tune5;
+module_param(tune5, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(tune5, "QUSB PHY TUNE5");
+
+
struct qusb_phy {
struct usb_phy phy;
void __iomem *base;
@@ -562,13 +580,29 @@ static int qusb_phy_init(struct usb_phy *phy)
qphy->base + QUSB2PHY_PORT_TUNE2);
}
- /* If tune2 modparam set, override tune2 value */
- if (tune2) {
- pr_debug("%s(): (modparam) TUNE2 val:0x%02x\n",
- __func__, tune2);
+ /* If tune modparam set, override tune value */
+
+ pr_debug("%s():userspecified modparams TUNEX val:0x%x %x %x %x %x\n",
+ __func__, tune1, tune2, tune3, tune4, tune5);
+ if (tune1)
+ writel_relaxed(tune1,
+ qphy->base + QUSB2PHY_PORT_TUNE1);
+
+ if (tune2)
writel_relaxed(tune2,
qphy->base + QUSB2PHY_PORT_TUNE2);
- }
+
+ if (tune3)
+ writel_relaxed(tune3,
+ qphy->base + QUSB2PHY_PORT_TUNE3);
+
+ if (tune4)
+ writel_relaxed(tune4,
+ qphy->base + QUSB2PHY_PORT_TUNE4);
+
+ if (tune5)
+ writel_relaxed(tune5,
+ qphy->base + QUSB2PHY_PORT_TUNE5);
/* ensure above writes are completed before re-enabling PHY */
wmb();
diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h
index 6182aa2c626e..bf4dc39f57ee 100644
--- a/drivers/video/fbdev/msm/mdss.h
+++ b/drivers/video/fbdev/msm/mdss.h
@@ -222,6 +222,7 @@ struct mdss_smmu_client {
struct dss_module_power mp;
struct reg_bus_client *reg_bus_clt;
bool domain_attached;
+ bool domain_reattach;
bool handoff_pending;
void __iomem *mmu_base;
struct list_head _client;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index b8f7a74ceede..e258f258aeca 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -4770,6 +4770,8 @@ static void __mdss_mdp_mixer_get_offsets(u32 mixer_num,
static inline int __mdss_mdp_mixer_get_hw_num(struct mdss_mdp_mixer *mixer)
{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+
/*
* mapping to hardware expectation of actual mixer programming to
* happen on following registers:
@@ -4777,6 +4779,11 @@ static inline int __mdss_mdp_mixer_get_hw_num(struct mdss_mdp_mixer *mixer)
* WB: 3, 4
* With some exceptions on certain revisions
*/
+
+ if (mdata->mdp_rev == MDSS_MDP_HW_REV_330
+ && mixer->num == MDSS_MDP_INTF_LAYERMIXER1)
+ return MDSS_MDP_INTF_LAYERMIXER2;
+
if (mixer->type == MDSS_MDP_MIXER_TYPE_WRITEBACK) {
u32 wb_offset;
diff --git a/drivers/video/fbdev/msm/mdss_smmu.c b/drivers/video/fbdev/msm/mdss_smmu.c
index 6930444118b6..62e25500060e 100644
--- a/drivers/video/fbdev/msm/mdss_smmu.c
+++ b/drivers/video/fbdev/msm/mdss_smmu.c
@@ -299,7 +299,6 @@ static int mdss_smmu_attach_v2(struct mdss_data_type *mdata)
for (i = 0; i < MDSS_IOMMU_MAX_DOMAIN; i++) {
if (!mdss_smmu_is_valid_domain_type(mdata, i))
continue;
-
mdss_smmu = mdss_smmu_get_cb(i);
if (mdss_smmu && mdss_smmu->base.dev) {
if (!mdss_smmu->handoff_pending) {
@@ -326,6 +325,14 @@ static int mdss_smmu_attach_v2(struct mdss_data_type *mdata)
goto err;
}
mdss_smmu->domain_attached = true;
+ if (mdss_smmu->domain_reattach) {
+ pr_debug("iommu v2 domain[%i] remove extra vote\n",
+ i);
+ /* remove extra power vote */
+ mdss_smmu_enable_power(mdss_smmu,
+ false);
+ mdss_smmu->domain_reattach = false;
+ }
pr_debug("iommu v2 domain[%i] attached\n", i);
}
} else {
@@ -379,6 +386,11 @@ static int mdss_smmu_detach_v2(struct mdss_data_type *mdata)
*/
arm_iommu_detach_device(mdss_smmu->base.dev);
mdss_smmu->domain_attached = false;
+ /*
+ * since we are leaving clocks on, on
+ * re-attach do not vote for clocks
+ */
+ mdss_smmu->domain_reattach = true;
pr_debug("iommu v2 domain[%i] detached\n", i);
} else {
mdss_smmu_enable_power(mdss_smmu, false);
diff --git a/include/dt-bindings/clock/qcom,gcc-sdm660.h b/include/dt-bindings/clock/qcom,gcc-sdm660.h
index cd5b78e59c5b..b622a662daa8 100644
--- a/include/dt-bindings/clock/qcom,gcc-sdm660.h
+++ b/include/dt-bindings/clock/qcom,gcc-sdm660.h
@@ -80,7 +80,6 @@
#define GCC_GPU_CFG_AHB_CLK 66
#define GCC_GPU_GPLL0_CLK 67
#define GCC_GPU_GPLL0_DIV_CLK 68
-#define GCC_HMSS_AHB_CLK 70
#define GCC_HMSS_DVM_BUS_CLK 71
#define GCC_HMSS_RBCPR_CLK 72
#define GCC_MMSS_GPLL0_CLK 73
@@ -169,7 +168,6 @@
#define GPLL6_OUT_MAIN 157
#define GPLL6_OUT_TEST 158
#define HLOS1_VOTE_LPASS_ADSP_SMMU_CLK 159
-#define HMSS_AHB_CLK_SRC 160
#define HMSS_GPLL0_CLK_SRC 161
#define HMSS_GPLL4_CLK_SRC 162
#define HMSS_RBCPR_CLK_SRC 163
diff --git a/include/linux/compaction.h b/include/linux/compaction.h
index 4cd4ddf64cc7..d7c8de583a23 100644
--- a/include/linux/compaction.h
+++ b/include/linux/compaction.h
@@ -52,6 +52,10 @@ extern void compaction_defer_reset(struct zone *zone, int order,
bool alloc_success);
extern bool compaction_restarting(struct zone *zone, int order);
+extern int kcompactd_run(int nid);
+extern void kcompactd_stop(int nid);
+extern void wakeup_kcompactd(pg_data_t *pgdat, int order, int classzone_idx);
+
#else
static inline unsigned long try_to_compact_pages(gfp_t gfp_mask,
unsigned int order, int alloc_flags,
@@ -84,6 +88,18 @@ static inline bool compaction_deferred(struct zone *zone, int order)
return true;
}
+static inline int kcompactd_run(int nid)
+{
+ return 0;
+}
+static inline void kcompactd_stop(int nid)
+{
+}
+
+static inline void wakeup_kcompactd(pg_data_t *pgdat, int order, int classzone_idx)
+{
+}
+
#endif /* CONFIG_COMPACTION */
#if defined(CONFIG_COMPACTION) && defined(CONFIG_SYSFS) && defined(CONFIG_NUMA)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index ddb3b927de39..45037a3a8e8e 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -689,6 +689,12 @@ typedef struct pglist_data {
mem_hotplug_begin/end() */
int kswapd_max_order;
enum zone_type classzone_idx;
+#ifdef CONFIG_COMPACTION
+ int kcompactd_max_order;
+ enum zone_type kcompactd_classzone_idx;
+ wait_queue_head_t kcompactd_wait;
+ struct task_struct *kcompactd;
+#endif
#ifdef CONFIG_NUMA_BALANCING
/* Lock serializing the migrate rate limiting window */
spinlock_t numabalancing_migrate_lock;
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 457d862cb9a8..1effc355d7d0 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -106,9 +106,10 @@ enum {
};
enum {
- POWER_SUPPLY_PARALLEL_NONE,
- POWER_SUPPLY_PARALLEL_USBIN_USBIN,
- POWER_SUPPLY_PARALLEL_MID_MID,
+ POWER_SUPPLY_PL_NONE,
+ POWER_SUPPLY_PL_USBIN_USBIN,
+ POWER_SUPPLY_PL_USBIN_USBIN_EXT,
+ POWER_SUPPLY_PL_USBMID_USBMID,
};
enum power_supply_property {
diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h
index 2a03a062a395..1534086e16d0 100644
--- a/include/linux/vm_event_item.h
+++ b/include/linux/vm_event_item.h
@@ -52,6 +52,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, PGPGOUTCLEAN, PSWPIN, PSWPOUT,
COMPACTMIGRATE_SCANNED, COMPACTFREE_SCANNED,
COMPACTISOLATED,
COMPACTSTALL, COMPACTFAIL, COMPACTSUCCESS,
+ KCOMPACTD_WAKE,
#endif
#ifdef CONFIG_HUGETLB_PAGE
HTLB_BUDDY_PGALLOC, HTLB_BUDDY_PGALLOC_FAIL,
diff --git a/include/trace/events/compaction.h b/include/trace/events/compaction.h
index c92d1e1cbad9..223450aeb49e 100644
--- a/include/trace/events/compaction.h
+++ b/include/trace/events/compaction.h
@@ -350,6 +350,61 @@ DEFINE_EVENT(mm_compaction_defer_template, mm_compaction_defer_reset,
);
#endif
+TRACE_EVENT(mm_compaction_kcompactd_sleep,
+
+ TP_PROTO(int nid),
+
+ TP_ARGS(nid),
+
+ TP_STRUCT__entry(
+ __field(int, nid)
+ ),
+
+ TP_fast_assign(
+ __entry->nid = nid;
+ ),
+
+ TP_printk("nid=%d", __entry->nid)
+);
+
+DECLARE_EVENT_CLASS(kcompactd_wake_template,
+
+ TP_PROTO(int nid, int order, enum zone_type classzone_idx),
+
+ TP_ARGS(nid, order, classzone_idx),
+
+ TP_STRUCT__entry(
+ __field(int, nid)
+ __field(int, order)
+ __field(enum zone_type, classzone_idx)
+ ),
+
+ TP_fast_assign(
+ __entry->nid = nid;
+ __entry->order = order;
+ __entry->classzone_idx = classzone_idx;
+ ),
+
+ TP_printk("nid=%d order=%d classzone_idx=%-8s",
+ __entry->nid,
+ __entry->order,
+ __print_symbolic(__entry->classzone_idx, ZONE_TYPE))
+);
+
+DEFINE_EVENT(kcompactd_wake_template, mm_compaction_wakeup_kcompactd,
+
+ TP_PROTO(int nid, int order, enum zone_type classzone_idx),
+
+ TP_ARGS(nid, order, classzone_idx)
+);
+
+DEFINE_EVENT(kcompactd_wake_template, mm_compaction_kcompactd_wake,
+
+ TP_PROTO(int nid, int order, enum zone_type classzone_idx),
+
+ TP_ARGS(nid, order, classzone_idx)
+);
+
#endif /* _TRACE_COMPACTION_H */
/* This part must be outside protection */
diff --git a/mm/compaction.c b/mm/compaction.c
index b4c33357f96e..538405d31c7f 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -7,6 +7,7 @@
*
* Copyright IBM Corp. 2007-2010 Mel Gorman <mel@csn.ul.ie>
*/
+#include <linux/cpu.h>
#include <linux/swap.h>
#include <linux/migrate.h>
#include <linux/compaction.h>
@@ -17,6 +18,8 @@
#include <linux/balloon_compaction.h>
#include <linux/page-isolation.h>
#include <linux/kasan.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
#include "internal.h"
#ifdef CONFIG_COMPACTION
@@ -1767,4 +1770,223 @@ void compaction_unregister_node(struct node *node)
}
#endif /* CONFIG_SYSFS && CONFIG_NUMA */
+static inline bool kcompactd_work_requested(pg_data_t *pgdat)
+{
+ return pgdat->kcompactd_max_order > 0;
+}
+
+static bool kcompactd_node_suitable(pg_data_t *pgdat)
+{
+ int zoneid;
+ struct zone *zone;
+ enum zone_type classzone_idx = pgdat->kcompactd_classzone_idx;
+
+ for (zoneid = 0; zoneid < classzone_idx; zoneid++) {
+ zone = &pgdat->node_zones[zoneid];
+
+ if (!populated_zone(zone))
+ continue;
+
+ if (compaction_suitable(zone, pgdat->kcompactd_max_order, 0,
+ classzone_idx) == COMPACT_CONTINUE)
+ return true;
+ }
+
+ return false;
+}
+
+static void kcompactd_do_work(pg_data_t *pgdat)
+{
+ /*
+ * With no special task, compact all zones so that a page of requested
+ * order is allocatable.
+ */
+ int zoneid;
+ struct zone *zone;
+ struct compact_control cc = {
+ .order = pgdat->kcompactd_max_order,
+ .classzone_idx = pgdat->kcompactd_classzone_idx,
+ .mode = MIGRATE_SYNC_LIGHT,
+ .ignore_skip_hint = true,
+
+ };
+ bool success = false;
+
+ trace_mm_compaction_kcompactd_wake(pgdat->node_id, cc.order,
+ cc.classzone_idx);
+ count_vm_event(KCOMPACTD_WAKE);
+
+ for (zoneid = 0; zoneid < cc.classzone_idx; zoneid++) {
+ int status;
+
+ zone = &pgdat->node_zones[zoneid];
+ if (!populated_zone(zone))
+ continue;
+
+ if (compaction_deferred(zone, cc.order))
+ continue;
+
+ if (compaction_suitable(zone, cc.order, 0, zoneid) !=
+ COMPACT_CONTINUE)
+ continue;
+
+ cc.nr_freepages = 0;
+ cc.nr_migratepages = 0;
+ cc.zone = zone;
+ INIT_LIST_HEAD(&cc.freepages);
+ INIT_LIST_HEAD(&cc.migratepages);
+
+ status = compact_zone(zone, &cc);
+
+ if (zone_watermark_ok(zone, cc.order, low_wmark_pages(zone),
+ cc.classzone_idx, 0)) {
+ success = true;
+ compaction_defer_reset(zone, cc.order, false);
+ } else if (status == COMPACT_COMPLETE) {
+ /*
+ * We use sync migration mode here, so we defer like
+ * sync direct compaction does.
+ */
+ defer_compaction(zone, cc.order);
+ }
+
+ VM_BUG_ON(!list_empty(&cc.freepages));
+ VM_BUG_ON(!list_empty(&cc.migratepages));
+ }
+
+ /*
+ * Regardless of success, we are done until woken up next. But remember
+ * the requested order/classzone_idx in case it was higher/tighter than
+ * our current ones
+ */
+ if (pgdat->kcompactd_max_order <= cc.order)
+ pgdat->kcompactd_max_order = 0;
+ if (pgdat->kcompactd_classzone_idx >= cc.classzone_idx)
+ pgdat->kcompactd_classzone_idx = pgdat->nr_zones - 1;
+}
+
+void wakeup_kcompactd(pg_data_t *pgdat, int order, int classzone_idx)
+{
+ if (!order)
+ return;
+
+ if (pgdat->kcompactd_max_order < order)
+ pgdat->kcompactd_max_order = order;
+
+ if (pgdat->kcompactd_classzone_idx > classzone_idx)
+ pgdat->kcompactd_classzone_idx = classzone_idx;
+
+ if (!waitqueue_active(&pgdat->kcompactd_wait))
+ return;
+
+ if (!kcompactd_node_suitable(pgdat))
+ return;
+
+ trace_mm_compaction_wakeup_kcompactd(pgdat->node_id, order,
+ classzone_idx);
+ wake_up_interruptible(&pgdat->kcompactd_wait);
+}
+
+/*
+ * The background compaction daemon, started as a kernel thread
+ * from the init process.
+ */
+static int kcompactd(void *p)
+{
+ pg_data_t *pgdat = (pg_data_t*)p;
+ struct task_struct *tsk = current;
+
+ const struct cpumask *cpumask = cpumask_of_node(pgdat->node_id);
+
+ if (!cpumask_empty(cpumask))
+ set_cpus_allowed_ptr(tsk, cpumask);
+
+ set_freezable();
+
+ pgdat->kcompactd_max_order = 0;
+ pgdat->kcompactd_classzone_idx = pgdat->nr_zones - 1;
+
+ while (!kthread_should_stop()) {
+ trace_mm_compaction_kcompactd_sleep(pgdat->node_id);
+ wait_event_freezable(pgdat->kcompactd_wait,
+ kcompactd_work_requested(pgdat));
+
+ kcompactd_do_work(pgdat);
+ }
+
+ return 0;
+}
+
+/*
+ * This kcompactd start function will be called by init and node-hot-add.
+ * On node-hot-add, kcompactd will moved to proper cpus if cpus are hot-added.
+ */
+int kcompactd_run(int nid)
+{
+ pg_data_t *pgdat = NODE_DATA(nid);
+ int ret = 0;
+
+ if (pgdat->kcompactd)
+ return 0;
+
+ pgdat->kcompactd = kthread_run(kcompactd, pgdat, "kcompactd%d", nid);
+ if (IS_ERR(pgdat->kcompactd)) {
+ pr_err("Failed to start kcompactd on node %d\n", nid);
+ ret = PTR_ERR(pgdat->kcompactd);
+ pgdat->kcompactd = NULL;
+ }
+ return ret;
+}
+
+/*
+ * Called by memory hotplug when all memory in a node is offlined. Caller must
+ * hold mem_hotplug_begin/end().
+ */
+void kcompactd_stop(int nid)
+{
+ struct task_struct *kcompactd = NODE_DATA(nid)->kcompactd;
+
+ if (kcompactd) {
+ kthread_stop(kcompactd);
+ NODE_DATA(nid)->kcompactd = NULL;
+ }
+}
+
+/*
+ * It's optimal to keep kcompactd on the same CPUs as their memory, but
+ * not required for correctness. So if the last cpu in a node goes
+ * away, we get changed to run anywhere: as the first one comes back,
+ * restore their cpu bindings.
+ */
+static int cpu_callback(struct notifier_block *nfb, unsigned long action,
+ void *hcpu)
+{
+ int nid;
+
+ if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN) {
+ for_each_node_state(nid, N_MEMORY) {
+ pg_data_t *pgdat = NODE_DATA(nid);
+ const struct cpumask *mask;
+
+ mask = cpumask_of_node(pgdat->node_id);
+
+ if (cpumask_any_and(cpu_online_mask, mask) < nr_cpu_ids)
+ /* One of our CPUs online: restore mask */
+ set_cpus_allowed_ptr(pgdat->kcompactd, mask);
+ }
+ }
+ return NOTIFY_OK;
+}
+
+static int __init kcompactd_init(void)
+{
+ int nid;
+
+ for_each_node_state(nid, N_MEMORY)
+ kcompactd_run(nid);
+ hotcpu_notifier(cpu_callback, 0);
+ return 0;
+}
+subsys_initcall(kcompactd_init)
+
#endif /* CONFIG_COMPACTION */
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index a042a9d537bb..91f7c074e385 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -32,6 +32,7 @@
#include <linux/hugetlb.h>
#include <linux/memblock.h>
#include <linux/bootmem.h>
+#include <linux/compaction.h>
#include <asm/tlbflush.h>
@@ -1012,7 +1013,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
arg.nr_pages = nr_pages;
node_states_check_changes_online(nr_pages, zone, &arg);
- nid = pfn_to_nid(pfn);
+ nid = zone_to_nid(zone);
ret = memory_notify(MEM_GOING_ONLINE, &arg);
ret = notifier_to_errno(ret);
@@ -1052,7 +1053,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
pgdat_resize_unlock(zone->zone_pgdat, &flags);
if (onlined_pages) {
- node_states_set_node(zone_to_nid(zone), &arg);
+ node_states_set_node(nid, &arg);
if (need_zonelists_rebuild)
build_all_zonelists(NULL, NULL);
else
@@ -1063,8 +1064,10 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
init_per_zone_wmark_min();
- if (onlined_pages)
- kswapd_run(zone_to_nid(zone));
+ if (onlined_pages) {
+ kswapd_run(nid);
+ kcompactd_run(nid);
+ }
vm_total_pages = nr_free_pagecache_pages();
@@ -1828,8 +1831,10 @@ repeat:
zone_pcp_update(zone);
node_states_clear_node(node, &arg);
- if (arg.status_change_nid >= 0)
+ if (arg.status_change_nid >= 0) {
kswapd_stop(node);
+ kcompactd_stop(node);
+ }
vm_total_pages = nr_free_pagecache_pages();
writeback_set_ratelimit();
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index c42587d02190..f9c0ca3f0098 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -5319,6 +5319,9 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat)
#endif
init_waitqueue_head(&pgdat->kswapd_wait);
init_waitqueue_head(&pgdat->pfmemalloc_wait);
+#ifdef CONFIG_COMPACTION
+ init_waitqueue_head(&pgdat->kcompactd_wait);
+#endif
pgdat_page_ext_init(pgdat);
for (j = 0; j < MAX_NR_ZONES; j++) {
diff --git a/mm/vmpressure.c b/mm/vmpressure.c
index f514dc40dab1..f5383e43597a 100644
--- a/mm/vmpressure.c
+++ b/mm/vmpressure.c
@@ -149,9 +149,16 @@ static unsigned long vmpressure_calc_pressure(unsigned long scanned,
unsigned long reclaimed)
{
unsigned long scale = scanned + reclaimed;
- unsigned long pressure;
+ unsigned long pressure = 0;
/*
+ * reclaimed can be greater than scanned in cases
+ * like THP, where the scanned is 1 and reclaimed
+ * could be 512
+ */
+ if (reclaimed >= scanned)
+ goto out;
+ /*
* We calculate the ratio (in percents) of how many pages were
* scanned vs. reclaimed in a given time frame (window). Note that
* time is in VM reclaimer's "ticks", i.e. number of pages
@@ -161,6 +168,7 @@ static unsigned long vmpressure_calc_pressure(unsigned long scanned,
pressure = scale - (reclaimed * scale / scanned);
pressure = pressure * 100 / scale;
+out:
pr_debug("%s: %3lu (s: %lu r: %lu)\n", __func__, pressure,
scanned, reclaimed);
diff --git a/mm/vmscan.c b/mm/vmscan.c
index ff408638fd95..03f91ee3c71a 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2547,15 +2547,23 @@ static bool shrink_zone(struct zone *zone, struct scan_control *sc,
sc->nr_scanned - nr_scanned,
zone_lru_pages);
+ /*
+ * Record the subtree's reclaim efficiency. The reclaimed
+ * pages from slab is excluded here because the corresponding
+ * scanned pages is not accounted. Moreover, freeing a page
+ * by slab shrinking depends on each slab's object population,
+ * making the cost model (i.e. scan:free) different from that
+ * of LRU.
+ */
+ vmpressure(sc->gfp_mask, sc->target_mem_cgroup,
+ sc->nr_scanned - nr_scanned,
+ sc->nr_reclaimed - nr_reclaimed);
+
if (reclaim_state) {
sc->nr_reclaimed += reclaim_state->reclaimed_slab;
reclaim_state->reclaimed_slab = 0;
}
- vmpressure(sc->gfp_mask, sc->target_mem_cgroup,
- sc->nr_scanned - nr_scanned,
- sc->nr_reclaimed - nr_reclaimed);
-
if (sc->nr_reclaimed - nr_reclaimed)
reclaimable = true;
@@ -3562,8 +3570,7 @@ static int kswapd(void *p)
* new request of a similar or harder type will succeed soon
* so consider going to sleep on the basis we reclaimed at
*/
- if (balanced_classzone_idx >= new_classzone_idx &&
- balanced_order == new_order) {
+ if (balanced_order == new_order) {
new_order = pgdat->kswapd_max_order;
new_classzone_idx = pgdat->classzone_idx;
pgdat->kswapd_max_order = 0;
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 77b8eabd5446..b8f2eda3381d 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -827,6 +827,7 @@ const char * const vmstat_text[] = {
"compact_stall",
"compact_fail",
"compact_success",
+ "compact_daemon_wake",
#endif
#ifdef CONFIG_HUGETLB_PAGE
diff --git a/net/socket.c b/net/socket.c
index 5211c40daecc..1cdfe02104a6 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1664,6 +1664,8 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
if (len > INT_MAX)
len = INT_MAX;
+ if (unlikely(!access_ok(VERIFY_READ, buff, len)))
+ return -EFAULT;
err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter);
if (unlikely(err))
@@ -1723,6 +1725,8 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
if (size > INT_MAX)
size = INT_MAX;
+ if (unlikely(!access_ok(VERIFY_WRITE, ubuf, size)))
+ return -EFAULT;
err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter);
if (unlikely(err))
return err;
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 6ecd300a18ac..337fc15aa28e 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -30,16 +30,6 @@ config SND_SOC_QDSP_DEBUG
is inducing kernel panic upon encountering critical
errors from DSP audio modules
-config DOLBY_DAP
- bool "Enable Dolby DAP"
- depends on SND_SOC_MSM_QDSP6V2_INTF
- help
- To add support for dolby DAP post processing.
- This support is to configure the post processing parameters
- to DSP. The configuration includes sending the end point
- device, end point dependent post processing parameters and
- the various posrt processing parameters
-
config DOLBY_DS2
bool "Enable Dolby DS2"
depends on SND_SOC_MSM_QDSP6V2_INTF
@@ -124,7 +114,7 @@ config SND_SOC_INT_CODEC
select SND_SOC_SDM660_CDC
select QTI_PP
select DTS_SRS_TM
- select DOLBY_DS2
+ select DOLBY_LICENSE
select SND_HWDEP
select MSM_ULTRASOUND
select DTS_EAGLE
@@ -156,7 +146,7 @@ config SND_SOC_EXT_CODEC
select MFD_CORE
select QTI_PP
select DTS_SRS_TM
- select DOLBY_DS2
+ select DOLBY_LICENSE
select SND_SOC_CPE
select SND_SOC_WCD_CPE
select SND_HWDEP
diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c
index e6fa1143af02..e7b51c5c2c00 100644
--- a/sound/soc/msm/msm8998.c
+++ b/sound/soc/msm/msm8998.c
@@ -421,7 +421,8 @@ static char const *usb_sample_rate_text[] = {"KHZ_8", "KHZ_11P025",
"KHZ_88P2", "KHZ_96", "KHZ_176P4",
"KHZ_192", "KHZ_352P8", "KHZ_384"};
static char const *ext_disp_sample_rate_text[] = {"KHZ_48", "KHZ_96",
- "KHZ_192"};
+ "KHZ_192", "KHZ_32", "KHZ_44P1",
+ "KHZ_88P2", "KHZ_176P4"};
static char const *tdm_ch_text[] = {"One", "Two", "Three", "Four",
"Five", "Six", "Seven", "Eight"};
static char const *tdm_bit_format_text[] = {"S16_LE", "S24_LE", "S32_LE"};
@@ -1500,6 +1501,22 @@ static int ext_disp_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
return idx;
switch (ext_disp_rx_cfg[idx].sample_rate) {
+ case SAMPLING_RATE_176P4KHZ:
+ sample_rate_val = 6;
+ break;
+
+ case SAMPLING_RATE_88P2KHZ:
+ sample_rate_val = 5;
+ break;
+
+ case SAMPLING_RATE_44P1KHZ:
+ sample_rate_val = 4;
+ break;
+
+ case SAMPLING_RATE_32KHZ:
+ sample_rate_val = 3;
+ break;
+
case SAMPLING_RATE_192KHZ:
sample_rate_val = 2;
break;
@@ -1530,6 +1547,18 @@ static int ext_disp_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
return idx;
switch (ucontrol->value.integer.value[0]) {
+ case 6:
+ ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_176P4KHZ;
+ break;
+ case 5:
+ ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_88P2KHZ;
+ break;
+ case 4:
+ ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_44P1KHZ;
+ break;
+ case 3:
+ ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_32KHZ;
+ break;
case 2:
ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_192KHZ;
break;
diff --git a/sound/soc/msm/qdsp6v2/Makefile b/sound/soc/msm/qdsp6v2/Makefile
index 469ab1a19c5b..d4db55fe06a2 100644
--- a/sound/soc/msm/qdsp6v2/Makefile
+++ b/sound/soc/msm/qdsp6v2/Makefile
@@ -10,7 +10,6 @@ obj-$(CONFIG_SND_SOC_QDSP6V2) += snd-soc-qdsp6v2.o msm-pcm-dtmf-v2.o \
msm-dai-stub-v2.o
obj-$(CONFIG_SND_HWDEP) += msm-pcm-routing-devdep.o
obj-$(CONFIG_DTS_EAGLE) += msm-dts-eagle.o
-obj-$(CONFIG_DOLBY_DAP) += msm-dolby-dap-config.o
obj-$(CONFIG_DOLBY_DS2) += msm-ds2-dap-config.o
obj-$(CONFIG_DOLBY_LICENSE) += msm-ds2-dap-config.o
obj-$(CONFIG_DTS_SRS_TM) += msm-dts-srs-tm-config.o
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
deleted file mode 100644
index 4664d39e87e0..000000000000
--- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
+++ /dev/null
@@ -1,1092 +0,0 @@
-/* Copyright (c) 2013-2014,2016-2017, 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/err.h>
-#include <linux/module.h>
-#include <linux/bitops.h>
-#include <sound/control.h>
-#include <sound/q6adm-v2.h>
-#include <sound/q6core.h>
-
-#include "msm-dolby-dap-config.h"
-
-#ifndef DOLBY_PARAM_VCNB_MAX_LENGTH
-#define DOLBY_PARAM_VCNB_MAX_LENGTH 40
-#endif
-
-/* dolby endp based parameters */
-struct dolby_dap_endp_params_s {
- int device;
- int device_ch_caps;
- int dap_device;
- int params_id[DOLBY_NUM_ENDP_DEPENDENT_PARAMS];
- int params_len[DOLBY_NUM_ENDP_DEPENDENT_PARAMS];
- int params_offset[DOLBY_NUM_ENDP_DEPENDENT_PARAMS];
- int params_val[DOLBY_ENDDEP_PARAM_LENGTH];
-};
-
-const struct dolby_dap_endp_params_s
- dolby_dap_endp_params[NUM_DOLBY_ENDP_DEVICE] = {
- {EARPIECE, 2, DOLBY_ENDP_EXT_SPEAKERS,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {SPEAKER, 2, DOLBY_ENDP_INT_SPEAKERS,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {WIRED_HEADSET, 2, DOLBY_ENDP_HEADPHONES,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {WIRED_HEADPHONE, 2, DOLBY_ENDP_HEADPHONES,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {BLUETOOTH_SCO, 2, DOLBY_ENDP_EXT_SPEAKERS,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {BLUETOOTH_SCO_HEADSET, 2, DOLBY_ENDP_EXT_SPEAKERS,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {BLUETOOTH_SCO_CARKIT, 2, DOLBY_ENDP_EXT_SPEAKERS,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {BLUETOOTH_A2DP, 2, DOLBY_ENDP_EXT_SPEAKERS,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {BLUETOOTH_A2DP_HEADPHONES, 2, DOLBY_ENDP_HEADPHONES,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {BLUETOOTH_A2DP_SPEAKER, 2, DOLBY_ENDP_EXT_SPEAKERS,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {AUX_DIGITAL, 2, DOLBY_ENDP_HDMI,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-496, -496, 0}
- },
- {AUX_DIGITAL, 6, DOLBY_ENDP_HDMI,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-496, -496, 0}
- },
- {AUX_DIGITAL, 8, DOLBY_ENDP_HDMI,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-496, -496, 0}
- },
- {ANLG_DOCK_HEADSET, 2, DOLBY_ENDP_HEADPHONES,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {DGTL_DOCK_HEADSET, 2, DOLBY_ENDP_HEADPHONES,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {USB_ACCESSORY, 2, DOLBY_ENDP_EXT_SPEAKERS,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {USB_DEVICE, 2, DOLBY_ENDP_EXT_SPEAKERS,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {REMOTE_SUBMIX, 2, DOLBY_ENDP_EXT_SPEAKERS,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {PROXY, 2, DOLBY_ENDP_EXT_SPEAKERS,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {PROXY, 6, DOLBY_ENDP_EXT_SPEAKERS,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {FM, 2, DOLBY_ENDP_EXT_SPEAKERS,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
- {FM_TX, 2, DOLBY_ENDP_EXT_SPEAKERS,
- {DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_VMB},
- {DOLBY_ENDDEP_PARAM_DVLO_LENGTH, DOLBY_ENDDEP_PARAM_DVLI_LENGTH,
- DOLBY_ENDDEP_PARAM_VMB_LENGTH},
- {DOLBY_ENDDEP_PARAM_DVLO_OFFSET, DOLBY_ENDDEP_PARAM_DVLI_OFFSET,
- DOLBY_ENDDEP_PARAM_VMB_OFFSET},
- {-320, -320, 144}
- },
-};
-
-/* dolby param ids to/from dsp */
-static uint32_t dolby_dap_params_id[ALL_DOLBY_PARAMS] = {
- DOLBY_PARAM_ID_VDHE, DOLBY_PARAM_ID_VSPE, DOLBY_PARAM_ID_DSSF,
- DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLE,
- DOLBY_PARAM_ID_DVMC, DOLBY_PARAM_ID_DVME, DOLBY_PARAM_ID_IENB,
- DOLBY_PARAM_ID_IEBF, DOLBY_PARAM_ID_IEON, DOLBY_PARAM_ID_DEON,
- DOLBY_PARAM_ID_NGON, DOLBY_PARAM_ID_GEON, DOLBY_PARAM_ID_GENB,
- DOLBY_PARAM_ID_GEBF, DOLBY_PARAM_ID_AONB, DOLBY_PARAM_ID_AOBF,
- DOLBY_PARAM_ID_AOBG, DOLBY_PARAM_ID_AOON, DOLBY_PARAM_ID_ARNB,
- DOLBY_PARAM_ID_ARBF, DOLBY_PARAM_ID_PLB, DOLBY_PARAM_ID_PLMD,
- DOLBY_PARAM_ID_DHSB, DOLBY_PARAM_ID_DHRG, DOLBY_PARAM_ID_DSSB,
- DOLBY_PARAM_ID_DSSA, DOLBY_PARAM_ID_DVLA, DOLBY_PARAM_ID_IEBT,
- DOLBY_PARAM_ID_IEA, DOLBY_PARAM_ID_DEA, DOLBY_PARAM_ID_DED,
- DOLBY_PARAM_ID_GEBG, DOLBY_PARAM_ID_AOCC, DOLBY_PARAM_ID_ARBI,
- DOLBY_PARAM_ID_ARBL, DOLBY_PARAM_ID_ARBH, DOLBY_PARAM_ID_AROD,
- DOLBY_PARAM_ID_ARTP, DOLBY_PARAM_ID_VMON, DOLBY_PARAM_ID_VMB,
- DOLBY_PARAM_ID_VCNB, DOLBY_PARAM_ID_VCBF, DOLBY_PARAM_ID_PREG,
- DOLBY_PARAM_ID_VEN, DOLBY_PARAM_ID_PSTG, DOLBY_COMMIT_ALL_TO_DSP,
- DOLBY_COMMIT_TO_DSP, DOLBY_USE_CACHE, DOLBY_AUTO_ENDP,
- DOLBY_AUTO_ENDDEP_PARAMS
-};
-
-/* modifed state: 0x00000000 - Not updated
-* > 0x00000000 && < 0x00010000
-* Updated and not commited to DSP
-* 0x00010001 - Updated and commited to DSP
-* > 0x00010001 - Modified the commited value
-*/
-static int dolby_dap_params_modified[MAX_DOLBY_PARAMS] = { 0 };
-/* param offset */
-static uint32_t dolby_dap_params_offset[MAX_DOLBY_PARAMS] = {
- DOLBY_PARAM_VDHE_OFFSET, DOLBY_PARAM_VSPE_OFFSET,
- DOLBY_PARAM_DSSF_OFFSET, DOLBY_PARAM_DVLI_OFFSET,
- DOLBY_PARAM_DVLO_OFFSET, DOLBY_PARAM_DVLE_OFFSET,
- DOLBY_PARAM_DVMC_OFFSET, DOLBY_PARAM_DVME_OFFSET,
- DOLBY_PARAM_IENB_OFFSET, DOLBY_PARAM_IEBF_OFFSET,
- DOLBY_PARAM_IEON_OFFSET, DOLBY_PARAM_DEON_OFFSET,
- DOLBY_PARAM_NGON_OFFSET, DOLBY_PARAM_GEON_OFFSET,
- DOLBY_PARAM_GENB_OFFSET, DOLBY_PARAM_GEBF_OFFSET,
- DOLBY_PARAM_AONB_OFFSET, DOLBY_PARAM_AOBF_OFFSET,
- DOLBY_PARAM_AOBG_OFFSET, DOLBY_PARAM_AOON_OFFSET,
- DOLBY_PARAM_ARNB_OFFSET, DOLBY_PARAM_ARBF_OFFSET,
- DOLBY_PARAM_PLB_OFFSET, DOLBY_PARAM_PLMD_OFFSET,
- DOLBY_PARAM_DHSB_OFFSET, DOLBY_PARAM_DHRG_OFFSET,
- DOLBY_PARAM_DSSB_OFFSET, DOLBY_PARAM_DSSA_OFFSET,
- DOLBY_PARAM_DVLA_OFFSET, DOLBY_PARAM_IEBT_OFFSET,
- DOLBY_PARAM_IEA_OFFSET, DOLBY_PARAM_DEA_OFFSET,
- DOLBY_PARAM_DED_OFFSET, DOLBY_PARAM_GEBG_OFFSET,
- DOLBY_PARAM_AOCC_OFFSET, DOLBY_PARAM_ARBI_OFFSET,
- DOLBY_PARAM_ARBL_OFFSET, DOLBY_PARAM_ARBH_OFFSET,
- DOLBY_PARAM_AROD_OFFSET, DOLBY_PARAM_ARTP_OFFSET,
- DOLBY_PARAM_VMON_OFFSET, DOLBY_PARAM_VMB_OFFSET,
- DOLBY_PARAM_VCNB_OFFSET, DOLBY_PARAM_VCBF_OFFSET,
- DOLBY_PARAM_PREG_OFFSET, DOLBY_PARAM_VEN_OFFSET,
- DOLBY_PARAM_PSTG_OFFSET
-};
-/* param_length */
-static uint32_t dolby_dap_params_length[MAX_DOLBY_PARAMS] = {
- DOLBY_PARAM_VDHE_LENGTH, DOLBY_PARAM_VSPE_LENGTH,
- DOLBY_PARAM_DSSF_LENGTH, DOLBY_PARAM_DVLI_LENGTH,
- DOLBY_PARAM_DVLO_LENGTH, DOLBY_PARAM_DVLE_LENGTH,
- DOLBY_PARAM_DVMC_LENGTH, DOLBY_PARAM_DVME_LENGTH,
- DOLBY_PARAM_IENB_LENGTH, DOLBY_PARAM_IEBF_LENGTH,
- DOLBY_PARAM_IEON_LENGTH, DOLBY_PARAM_DEON_LENGTH,
- DOLBY_PARAM_NGON_LENGTH, DOLBY_PARAM_GEON_LENGTH,
- DOLBY_PARAM_GENB_LENGTH, DOLBY_PARAM_GEBF_LENGTH,
- DOLBY_PARAM_AONB_LENGTH, DOLBY_PARAM_AOBF_LENGTH,
- DOLBY_PARAM_AOBG_LENGTH, DOLBY_PARAM_AOON_LENGTH,
- DOLBY_PARAM_ARNB_LENGTH, DOLBY_PARAM_ARBF_LENGTH,
- DOLBY_PARAM_PLB_LENGTH, DOLBY_PARAM_PLMD_LENGTH,
- DOLBY_PARAM_DHSB_LENGTH, DOLBY_PARAM_DHRG_LENGTH,
- DOLBY_PARAM_DSSB_LENGTH, DOLBY_PARAM_DSSA_LENGTH,
- DOLBY_PARAM_DVLA_LENGTH, DOLBY_PARAM_IEBT_LENGTH,
- DOLBY_PARAM_IEA_LENGTH, DOLBY_PARAM_DEA_LENGTH,
- DOLBY_PARAM_DED_LENGTH, DOLBY_PARAM_GEBG_LENGTH,
- DOLBY_PARAM_AOCC_LENGTH, DOLBY_PARAM_ARBI_LENGTH,
- DOLBY_PARAM_ARBL_LENGTH, DOLBY_PARAM_ARBH_LENGTH,
- DOLBY_PARAM_AROD_LENGTH, DOLBY_PARAM_ARTP_LENGTH,
- DOLBY_PARAM_VMON_LENGTH, DOLBY_PARAM_VMB_LENGTH,
- DOLBY_PARAM_VCNB_LENGTH, DOLBY_PARAM_VCBF_LENGTH,
- DOLBY_PARAM_PREG_LENGTH, DOLBY_PARAM_VEN_LENGTH,
- DOLBY_PARAM_PSTG_LENGTH
-};
-
-/* param_value */
-static uint32_t dolby_dap_params_value[TOTAL_LENGTH_DOLBY_PARAM] = {0};
-
-struct dolby_dap_params_get_s {
- int32_t port_id;
- uint32_t device_id;
- uint32_t param_id;
- uint32_t offset;
- uint32_t length;
-};
-
-struct dolby_dap_params_states_s {
- bool use_cache;
- bool auto_endp;
- bool enddep_params;
- int port_id[AFE_MAX_PORTS];
- int copp_idx[AFE_MAX_PORTS];
- int port_open_count;
- int port_ids_dolby_can_be_enabled;
- int device;
-};
-
-static struct dolby_dap_params_get_s dolby_dap_params_get = {-1, DEVICE_OUT_ALL,
- 0, 0, 0};
-static struct dolby_dap_params_states_s dolby_dap_params_states = { true, true,
- true, {DOLBY_INVALID_PORT_ID},
- {-1}, 0, DEVICE_OUT_ALL, 0 };
-/*
-port_ids_dolby_can_be_enabled is set to 0x7FFFFFFF.
-this needs to be removed after interface validation
-*/
-
-static int msm_dolby_dap_map_device_to_dolby_endpoint(int device)
-{
- int i, dolby_dap_device = DOLBY_ENDP_EXT_SPEAKERS;
- for (i = 0; i < NUM_DOLBY_ENDP_DEVICE; i++) {
- if (dolby_dap_endp_params[i].device == device) {
- dolby_dap_device = dolby_dap_endp_params[i].dap_device;
- break;
- }
- }
- /* default the endpoint to speaker if corresponding device entry */
- /* not found */
- if (i >= NUM_DOLBY_ENDP_DEVICE)
- dolby_dap_params_states.device = SPEAKER;
- return dolby_dap_device;
-}
-
-static int msm_dolby_dap_send_end_point(int port_id, int copp_idx)
-{
- int rc = 0;
- char *params_value;
- int *update_params_value;
- uint32_t params_length = (DOLBY_PARAM_INT_ENDP_LENGTH +
- DOLBY_PARAM_PAYLOAD_SIZE) * sizeof(uint32_t);
-
- pr_debug("%s\n", __func__);
- params_value = kzalloc(params_length, GFP_KERNEL);
- if (!params_value) {
- pr_err("%s, params memory alloc failed", __func__);
- return -ENOMEM;
- }
- update_params_value = (int *)params_value;
- *update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
- *update_params_value++ = DOLBY_PARAM_ID_INIT_ENDP;
- *update_params_value++ = DOLBY_PARAM_INT_ENDP_LENGTH * sizeof(uint32_t);
- *update_params_value++ =
- msm_dolby_dap_map_device_to_dolby_endpoint(
- dolby_dap_params_states.device);
- rc = adm_dolby_dap_send_params(port_id, copp_idx, params_value,
- params_length);
- if (rc) {
- pr_err("%s: send dolby params failed\n", __func__);
- rc = -EINVAL;
- }
- kfree(params_value);
- return rc;
-}
-
-static int msm_dolby_dap_send_enddep_params(int port_id, int copp_idx,
- int device_channels)
-{
- int i, j, rc = 0, idx, offset;
- char *params_value;
- int *update_params_value;
- uint32_t params_length = (DOLBY_ENDDEP_PARAM_LENGTH +
- DOLBY_NUM_ENDP_DEPENDENT_PARAMS *
- DOLBY_PARAM_PAYLOAD_SIZE) *
- sizeof(uint32_t);
-
- pr_debug("%s\n", __func__);
- params_value = kzalloc(params_length, GFP_KERNEL);
- if (!params_value) {
- pr_err("%s, params memory alloc failed", __func__);
- return -ENOMEM;
- }
- update_params_value = (int *)params_value;
- for (idx = 0; idx < NUM_DOLBY_ENDP_DEVICE; idx++) {
- if (dolby_dap_endp_params[idx].device ==
- dolby_dap_params_states.device) {
- if (dolby_dap_params_states.device == AUX_DIGITAL ||
- dolby_dap_params_states.device == PROXY) {
- if (dolby_dap_endp_params[idx].device_ch_caps ==
- device_channels)
- break;
- } else {
- break;
- }
- }
- }
- if (idx >= NUM_DOLBY_ENDP_DEVICE) {
- pr_err("%s: device is not set accordingly\n", __func__);
- kfree(params_value);
- return -EINVAL;
- }
- for (i = 0; i < DOLBY_ENDDEP_PARAM_LENGTH; i++) {
- *update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
- *update_params_value++ =
- dolby_dap_endp_params[idx].params_id[i];
- *update_params_value++ =
- dolby_dap_endp_params[idx].params_len[i] *
- sizeof(uint32_t);
- offset = dolby_dap_endp_params[idx].params_offset[i];
- for (j = 0; j < dolby_dap_endp_params[idx].params_len[i]; j++)
- *update_params_value++ =
- dolby_dap_endp_params[idx].params_val[offset+j];
- }
- rc = adm_dolby_dap_send_params(port_id, copp_idx, params_value,
- params_length);
- if (rc) {
- pr_err("%s: send dolby params failed\n", __func__);
- rc = -EINVAL;
- }
- kfree(params_value);
- return rc;
-}
-
-static int msm_dolby_dap_send_cached_params(int port_id, int copp_idx,
- int commit)
-{
- char *params_value;
- int *update_params_value, rc = 0;
- uint32_t index_offset, i, j;
- uint32_t params_length = (TOTAL_LENGTH_DOLBY_PARAM +
- MAX_DOLBY_PARAMS * DOLBY_PARAM_PAYLOAD_SIZE) *
- sizeof(uint32_t);
-
- params_value = kzalloc(params_length, GFP_KERNEL);
- if (!params_value) {
- pr_err("%s, params memory alloc failed\n", __func__);
- return -ENOMEM;
- }
- update_params_value = (int *)params_value;
- params_length = 0;
- for (i = 0; i < MAX_DOLBY_PARAMS; i++) {
- if ((dolby_dap_params_modified[i] == 0) ||
- ((commit) &&
- ((dolby_dap_params_modified[i] & 0x00010000) &&
- ((dolby_dap_params_modified[i] & 0x0000FFFF) <= 1))))
- continue;
- *update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
- *update_params_value++ = dolby_dap_params_id[i];
- *update_params_value++ = dolby_dap_params_length[i] *
- sizeof(uint32_t);
- index_offset = dolby_dap_params_offset[i];
- for (j = 0; j < dolby_dap_params_length[i]; j++) {
- *update_params_value++ =
- dolby_dap_params_value[index_offset+j];
- }
- params_length += (DOLBY_PARAM_PAYLOAD_SIZE +
- dolby_dap_params_length[i]) * sizeof(uint32_t);
- }
- pr_debug("%s, valid param length: %d", __func__, params_length);
- if (params_length) {
- rc = adm_dolby_dap_send_params(port_id, copp_idx, params_value,
- params_length);
- if (rc) {
- pr_err("%s: send dolby params failed\n", __func__);
- kfree(params_value);
- return -EINVAL;
- }
- for (i = 0; i < MAX_DOLBY_PARAMS; i++) {
- if ((dolby_dap_params_modified[i] == 0) ||
- ((commit) &&
- ((dolby_dap_params_modified[i] & 0x00010000) &&
- ((dolby_dap_params_modified[i] & 0x0000FFFF) <= 1))
- ))
- continue;
- dolby_dap_params_modified[i] = 0x00010001;
- }
- }
- kfree(params_value);
- return 0;
-}
-
-int msm_dolby_dap_init(int port_id, int copp_idx, int channels,
- bool is_custom_stereo_on)
-{
- int ret = 0;
- int index = adm_validate_and_get_port_index(port_id);
- if (index < 0) {
- pr_err("%s: Invalid port idx %d port_id %#x\n", __func__, index,
- port_id);
- return -EINVAL;
- }
- if ((port_id != DOLBY_INVALID_PORT_ID) &&
- (port_id & dolby_dap_params_states.port_ids_dolby_can_be_enabled)) {
- dolby_dap_params_states.port_id[index] = port_id;
- dolby_dap_params_states.copp_idx[index] = copp_idx;
- dolby_dap_params_states.port_open_count++;
- if (dolby_dap_params_states.auto_endp) {
- ret = msm_dolby_dap_send_end_point(port_id, copp_idx);
- if (ret) {
- pr_err("%s: err sending endppoint\n", __func__);
- return ret;
- }
- }
- if (dolby_dap_params_states.use_cache) {
- ret = msm_dolby_dap_send_cached_params(port_id,
- copp_idx, 0);
- if (ret) {
- pr_err("%s: err sending cached params\n",
- __func__);
- return ret;
- }
- }
- if (dolby_dap_params_states.enddep_params) {
- msm_dolby_dap_send_enddep_params(port_id, copp_idx,
- channels);
- if (ret) {
- pr_err("%s: err sending endp dependent params\n",
- __func__);
- return ret;
- }
- }
- if (is_custom_stereo_on)
- dolby_dap_set_custom_stereo_onoff(port_id, copp_idx,
- is_custom_stereo_on);
- }
- return ret;
-}
-
-void msm_dolby_dap_deinit(int port_id)
-{
- int index = adm_validate_and_get_port_index(port_id);
- if (index < 0) {
- pr_err("%s: Invalid port idx %d port_id %#x\n", __func__, index,
- port_id);
- return;
- }
- dolby_dap_params_states.port_open_count--;
- if ((dolby_dap_params_states.port_id[index] == port_id) &&
- (!dolby_dap_params_states.port_open_count)) {
- dolby_dap_params_states.port_id[index] = DOLBY_INVALID_PORT_ID;
- dolby_dap_params_states.copp_idx[index] = -1;
- }
-}
-
-static int msm_dolby_dap_set_vspe_vdhe(int port_id, int copp_idx,
- bool is_custom_stereo_enabled)
-{
- char *params_value;
- int *update_params_value, rc = 0;
- uint32_t index_offset, i, j;
- uint32_t params_length = (TOTAL_LENGTH_DOLBY_PARAM +
- 2 * DOLBY_PARAM_PAYLOAD_SIZE) *
- sizeof(uint32_t);
- if (port_id == DOLBY_INVALID_PORT_ID) {
- pr_err("%s: Not a Dolby topology. Do not set custom stereo mixing\n",
- __func__);
- return -EINVAL;
- }
- params_value = kzalloc(params_length, GFP_KERNEL);
- if (!params_value) {
- pr_err("%s, params memory alloc failed\n", __func__);
- return -ENOMEM;
- }
- update_params_value = (int *)params_value;
- params_length = 0;
- /* for VDHE and VSPE DAP params at index 0 and 1 in table */
- for (i = 0; i < 2; i++) {
- *update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
- *update_params_value++ = dolby_dap_params_id[i];
- *update_params_value++ = dolby_dap_params_length[i] *
- sizeof(uint32_t);
- index_offset = dolby_dap_params_offset[i];
- for (j = 0; j < dolby_dap_params_length[i]; j++) {
- if (is_custom_stereo_enabled)
- *update_params_value++ = 0;
- else
- *update_params_value++ =
- dolby_dap_params_value[index_offset+j];
- }
- params_length += (DOLBY_PARAM_PAYLOAD_SIZE +
- dolby_dap_params_length[i]) * sizeof(uint32_t);
- }
- pr_debug("%s, valid param length: %d", __func__, params_length);
- if (params_length) {
- rc = adm_dolby_dap_send_params(port_id, copp_idx, params_value,
- params_length);
- if (rc) {
- pr_err("%s: send vdhe/vspe params failed with rc=%d\n",
- __func__, rc);
- kfree(params_value);
- return -EINVAL;
- }
- }
- kfree(params_value);
- return 0;
-}
-
-int dolby_dap_set_custom_stereo_onoff(int port_id, int copp_idx,
- bool is_custom_stereo_enabled)
-{
- char *params_value;
- int *update_params_value, rc = 0;
- uint32_t params_length = (TOTAL_LENGTH_DOLBY_PARAM +
- DOLBY_PARAM_PAYLOAD_SIZE) *
- sizeof(uint32_t);
- if (port_id == DOLBY_INVALID_PORT_ID)
- return -EINVAL;
-
- msm_dolby_dap_set_vspe_vdhe(port_id, copp_idx,
- is_custom_stereo_enabled);
- params_value = kzalloc(params_length, GFP_KERNEL);
- if (!params_value) {
- pr_err("%s, params memory alloc failed\n", __func__);
- return -ENOMEM;
- }
- update_params_value = (int *)params_value;
- params_length = 0;
- *update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
- *update_params_value++ = DOLBY_ENABLE_CUSTOM_STEREO;
- *update_params_value++ = sizeof(uint32_t);
- if (is_custom_stereo_enabled)
- *update_params_value++ = 1;
- else
- *update_params_value++ = 0;
- params_length += (DOLBY_PARAM_PAYLOAD_SIZE + 1) * sizeof(uint32_t);
- pr_debug("%s, valid param length: %d", __func__, params_length);
- if (params_length) {
- rc = adm_dolby_dap_send_params(port_id, copp_idx, params_value,
- params_length);
- if (rc) {
- pr_err("%s: setting ds1 custom stereo param failed with rc=%d\n",
- __func__, rc);
- kfree(params_value);
- return -EINVAL;
- }
- }
- kfree(params_value);
- return 0;
-}
-
-static int msm_dolby_dap_map_device_to_port_id(int device)
-{
- int port_id = SLIMBUS_0_RX;
- device = DEVICE_OUT_ALL;
- /*update the device when single stream to multiple device is handled*/
- if (device == DEVICE_OUT_ALL) {
- port_id = PRIMARY_I2S_RX | SLIMBUS_0_RX | HDMI_RX |
- INT_BT_SCO_RX | INT_FM_RX |
- RT_PROXY_PORT_001_RX |
- AFE_PORT_ID_PRIMARY_PCM_RX |
- MI2S_RX | SECONDARY_I2S_RX |
- SLIMBUS_1_RX | SLIMBUS_4_RX | SLIMBUS_3_RX |
- AFE_PORT_ID_SECONDARY_MI2S_RX;
- } else {
- /* update port_id based on the device */
- }
- return port_id;
-}
-
-int msm_dolby_dap_param_to_set_control_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- /* not used while setting the parameters */
- return 0;
-}
-
-int msm_dolby_dap_param_to_set_control_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- int rc = 0, port_id, copp_idx;
- uint32_t idx, j, current_offset;
- uint32_t device = ucontrol->value.integer.value[0];
- uint32_t param_id = ucontrol->value.integer.value[1];
- uint32_t offset = ucontrol->value.integer.value[2];
- uint32_t length = ucontrol->value.integer.value[3];
-
- dolby_dap_params_states.port_ids_dolby_can_be_enabled =
- msm_dolby_dap_map_device_to_port_id(device);
- for (idx = 0; idx < ALL_DOLBY_PARAMS; idx++) {
- /*paramid from user space*/
- if (param_id == dolby_dap_params_id[idx])
- break;
- }
- if (idx > ALL_DOLBY_PARAMS-1) {
- pr_err("%s: invalid param id 0x%x to set\n", __func__,
- param_id);
- return -EINVAL;
- }
- switch (idx) {
- case DOLBY_COMMIT_ALL_IDX: {
- /* COMIIT ALL: Send all parameters to DSP */
- pr_debug("%s: COMMIT_ALL recvd\n", __func__);
- for (idx = 0; idx < AFE_MAX_PORTS; idx++) {
- port_id = dolby_dap_params_states.port_id[idx];
- copp_idx =
- dolby_dap_params_states.copp_idx[idx];
- if ((copp_idx > 0) &&
- (copp_idx < MAX_COPPS_PER_PORT) &&
- (port_id != DOLBY_INVALID_PORT_ID))
- rc |= msm_dolby_dap_send_cached_params(
- port_id,
- copp_idx,
- 0);
- }
- }
- break;
- case DOLBY_COMMIT_IDX: {
- pr_debug("%s: COMMIT recvd\n", __func__);
- /* COMMIT: Send only modified paramters to DSP */
- for (idx = 0; idx < AFE_MAX_PORTS; idx++) {
- port_id = dolby_dap_params_states.port_id[idx];
- copp_idx =
- dolby_dap_params_states.copp_idx[idx];
- if ((copp_idx > 0) &&
- (copp_idx < MAX_COPPS_PER_PORT) &&
- (port_id == DOLBY_INVALID_PORT_ID))
- rc |= msm_dolby_dap_send_cached_params(
- port_id,
- copp_idx,
- 1);
- }
- }
- break;
- case DOLBY_USE_CACHE_IDX: {
- pr_debug("%s: USE CACHE recvd val: %ld\n", __func__,
- ucontrol->value.integer.value[4]);
- dolby_dap_params_states.use_cache =
- ucontrol->value.integer.value[4];
- }
- break;
- case DOLBY_AUTO_ENDP_IDX: {
- pr_debug("%s: AUTO_ENDP recvd val: %ld\n", __func__,
- ucontrol->value.integer.value[4]);
- dolby_dap_params_states.auto_endp =
- ucontrol->value.integer.value[4];
- }
- break;
- case DOLBY_AUTO_ENDDEP_IDX: {
- pr_debug("%s: USE_ENDDEP_PARAMS recvd val: %ld\n",
- __func__, ucontrol->value.integer.value[4]);
- dolby_dap_params_states.enddep_params =
- ucontrol->value.integer.value[4];
- }
- break;
- default: {
- /* cache the parameters */
- dolby_dap_params_modified[idx] += 1;
- current_offset = dolby_dap_params_offset[idx] + offset;
- if (current_offset >= TOTAL_LENGTH_DOLBY_PARAM) {
- pr_err("%s: invalid offset %d at idx %d\n",
- __func__, offset, idx);
- return -EINVAL;
- }
- if ((length == 0) || (current_offset + length - 1
- < current_offset) || (current_offset + length
- > TOTAL_LENGTH_DOLBY_PARAM)) {
- pr_err("%s: invalid length %d at idx %d\n",
- __func__, length, idx);
- return -EINVAL;
- }
- dolby_dap_params_length[idx] = length;
- pr_debug("%s: param recvd deviceId=0x%x paramId=0x%x offset=%d length=%d\n",
- __func__, device, param_id, offset, length);
- for (j = 0; j < length; j++) {
- dolby_dap_params_value[
- dolby_dap_params_offset[idx] +
- offset + j]
- = ucontrol->value.integer.value[4+j];
- pr_debug("value[%d]: %ld\n", j,
- ucontrol->value.integer.value[4+j]);
- }
- }
- }
-
- return rc;
-}
-
-int msm_dolby_dap_param_to_get_control_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- int rc = 0, i, index;
- char *params_value;
- int *update_params_value;
- uint32_t params_length = DOLBY_MAX_LENGTH_INDIVIDUAL_PARAM *
- sizeof(uint32_t);
- uint32_t param_payload_len =
- DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t);
- int port_id = dolby_dap_params_get.port_id, copp_idx;
-
- if (port_id == DOLBY_INVALID_PORT_ID) {
- pr_err("%s, port_id not set, do not query ADM\n", __func__);
- return -EINVAL;
- }
- index = adm_validate_and_get_port_index(port_id);
- if (index < 0) {
- pr_err("%s: Invalid port idx %d port_id %#x\n", __func__, index,
- port_id);
- return -EINVAL;
- }
- copp_idx = dolby_dap_params_states.copp_idx[index];
- if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) {
- pr_debug("%s: get params called before copp open.copp_idx:%d\n",
- __func__, copp_idx);
- return -EINVAL;
- }
- if (dolby_dap_params_get.length > 128 - DOLBY_PARAM_PAYLOAD_SIZE) {
- pr_err("%s: Incorrect parameter length", __func__);
- return -EINVAL;
- }
- params_value = kzalloc(params_length + param_payload_len, GFP_KERNEL);
- if (!params_value) {
- pr_err("%s, params memory alloc failed\n", __func__);
- return -ENOMEM;
- }
- if (DOLBY_PARAM_ID_VER == dolby_dap_params_get.param_id) {
- rc = adm_get_params(port_id, copp_idx,
- DOLBY_BUNDLE_MODULE_ID, DOLBY_PARAM_ID_VER,
- params_length + param_payload_len,
- params_value);
- } else {
- for (i = 0; i < MAX_DOLBY_PARAMS; i++)
- if (dolby_dap_params_id[i] ==
- dolby_dap_params_get.param_id)
- break;
- if (i > MAX_DOLBY_PARAMS-1) {
- pr_err("%s: invalid param id to set", __func__);
- rc = -EINVAL;
- } else {
- params_length = dolby_dap_params_length[i] *
- sizeof(uint32_t);
- rc = adm_get_params(port_id, copp_idx,
- DOLBY_BUNDLE_MODULE_ID,
- dolby_dap_params_id[i],
- params_length + param_payload_len,
- params_value);
- }
- }
- if (rc) {
- pr_err("%s: get parameters failed rc:%d\n", __func__, rc);
- kfree(params_value);
- return -EINVAL;
- }
- update_params_value = (int *)params_value;
- ucontrol->value.integer.value[0] = dolby_dap_params_get.device_id;
- ucontrol->value.integer.value[1] = dolby_dap_params_get.param_id;
- ucontrol->value.integer.value[2] = dolby_dap_params_get.offset;
- ucontrol->value.integer.value[3] = dolby_dap_params_get.length;
-
- pr_debug("%s: FROM DSP value[0] 0x%x value[1] %d value[2] 0x%x\n",
- __func__, update_params_value[0],
- update_params_value[1], update_params_value[2]);
- for (i = 0; i < dolby_dap_params_get.length; i++) {
- ucontrol->value.integer.value[DOLBY_PARAM_PAYLOAD_SIZE+i] =
- update_params_value[i];
- pr_debug("value[%d]:%d\n", i, update_params_value[i]);
- }
- pr_debug("%s: Returning param_id=0x%x offset=%d length=%d\n",
- __func__, dolby_dap_params_get.param_id,
- dolby_dap_params_get.offset,
- dolby_dap_params_get.length);
- kfree(params_value);
- return 0;
-}
-
-int msm_dolby_dap_param_to_get_control_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- int port_id, idx, copp_idx;
- dolby_dap_params_get.device_id = ucontrol->value.integer.value[0];
- port_id = msm_dolby_dap_map_device_to_port_id(
- dolby_dap_params_get.device_id);
- for (idx = 0; idx < AFE_MAX_PORTS; idx++) {
- port_id = dolby_dap_params_states.port_id[idx];
- copp_idx = dolby_dap_params_states.copp_idx[idx];
- if ((copp_idx < 0) ||
- (copp_idx >= MAX_COPPS_PER_PORT) ||
- (port_id == DOLBY_INVALID_PORT_ID))
- continue;
- else
- break;
- }
- if (idx == AFE_MAX_PORTS)
- port_id = SLIMBUS_0_RX;
- dolby_dap_params_get.port_id = port_id;
- dolby_dap_params_get.param_id = ucontrol->value.integer.value[1];
- dolby_dap_params_get.offset = ucontrol->value.integer.value[2];
- dolby_dap_params_get.length = ucontrol->value.integer.value[3];
- pr_debug("%s: param_id=0x%x offset=%d length=%d\n", __func__,
- dolby_dap_params_get.param_id, dolby_dap_params_get.offset,
- dolby_dap_params_get.length);
- return 0;
-}
-
-int msm_dolby_dap_param_visualizer_control_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- uint32_t length = dolby_dap_params_value[DOLBY_PARAM_VCNB_OFFSET];
- char *visualizer_data;
- int i, rc;
- int *update_visualizer_data;
- uint32_t offset, params_length =
- (2*length + DOLBY_VIS_PARAM_HEADER_SIZE)*sizeof(uint32_t);
- uint32_t param_payload_len =
- DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t);
- int port_id, copp_idx, idx;
- if (length > DOLBY_PARAM_VCNB_MAX_LENGTH || length <= 0) {
- pr_err("%s Incorrect VCNB length", __func__);
- ucontrol->value.integer.value[0] = 0;
- return -EINVAL;
- }
- for (idx = 0; idx < AFE_MAX_PORTS; idx++) {
- port_id = dolby_dap_params_states.port_id[idx];
- copp_idx = dolby_dap_params_states.copp_idx[idx];
- if ((copp_idx < 0) ||
- (copp_idx >= MAX_COPPS_PER_PORT) ||
- (port_id == DOLBY_INVALID_PORT_ID))
- continue;
- else
- break;
- }
- if (idx == AFE_MAX_PORTS) {
- pr_debug("%s, port_id not set, returning error", __func__);
- ucontrol->value.integer.value[0] = 0;
- return -EINVAL;
- }
- visualizer_data = kzalloc(params_length, GFP_KERNEL);
- if (!visualizer_data) {
- pr_err("%s, params memory alloc failed\n", __func__);
- return -ENOMEM;
- }
- offset = 0;
- params_length = length * sizeof(uint32_t);
- rc = adm_get_params(port_id, copp_idx, DOLBY_BUNDLE_MODULE_ID,
- DOLBY_PARAM_ID_VCBG,
- params_length + param_payload_len,
- visualizer_data + offset);
- if (rc) {
- pr_err("%s: get parameters failed\n", __func__);
- kfree(visualizer_data);
- return -EINVAL;
- }
-
- offset = length * sizeof(uint32_t);
- rc = adm_get_params(port_id, copp_idx, DOLBY_BUNDLE_MODULE_ID,
- DOLBY_PARAM_ID_VCBE,
- params_length + param_payload_len,
- visualizer_data + offset);
- if (rc) {
- pr_err("%s: get parameters failed\n", __func__);
- kfree(visualizer_data);
- return -EINVAL;
- }
-
- ucontrol->value.integer.value[0] = 2*length;
- pr_debug("%s: visualizer data length %ld\n", __func__,
- ucontrol->value.integer.value[0]);
- update_visualizer_data = (int *)visualizer_data;
- for (i = 0; i < 2*length; i++) {
- ucontrol->value.integer.value[1+i] = update_visualizer_data[i];
- pr_debug("value[%d] %d\n", i, update_visualizer_data[i]);
- }
- kfree(visualizer_data);
- return 0;
-}
-
-int msm_dolby_dap_param_visualizer_control_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- /* not used while getting the visualizer data */
- return 0;
-}
-
-int msm_dolby_dap_endpoint_control_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- /* not used while setting the endpoint */
- return 0;
-}
-
-int msm_dolby_dap_endpoint_control_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- int device = ucontrol->value.integer.value[0];
- dolby_dap_params_states.device = device;
- return 0;
-}
-
-int msm_dolby_dap_security_control_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- /* not used while setting the manfr id*/
- return 0;
-}
-
-int msm_dolby_dap_security_control_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- int manufacturer_id = ucontrol->value.integer.value[0];
- core_set_dolby_manufacturer_id(manufacturer_id);
- return 0;
-}
-
-int msm_dolby_dap_license_control_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- ucontrol->value.integer.value[0] =
- core_get_license_status(DOLBY_DS1_LICENSE_ID);
- return 0;
-}
-
-int msm_dolby_dap_license_control_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- return core_set_license(ucontrol->value.integer.value[0],
- DOLBY_DS1_LICENSE_ID);
-}
-
-static const struct snd_kcontrol_new dolby_license_controls[] = {
- SOC_SINGLE_MULTI_EXT("DS1 License", SND_SOC_NOPM, 0,
- 0xFFFFFFFF, 0, 1, msm_dolby_dap_license_control_get,
- msm_dolby_dap_license_control_put),
-};
-
-static const struct snd_kcontrol_new dolby_security_controls[] = {
- SOC_SINGLE_MULTI_EXT("DS1 Security", SND_SOC_NOPM, 0,
- 0xFFFFFFFF, 0, 1, msm_dolby_dap_security_control_get,
- msm_dolby_dap_security_control_put),
-};
-
-static const struct snd_kcontrol_new dolby_dap_param_to_set_controls[] = {
- SOC_SINGLE_MULTI_EXT("DS1 DAP Set Param", SND_SOC_NOPM, 0, 0xFFFFFFFF,
- 0, 128, msm_dolby_dap_param_to_set_control_get,
- msm_dolby_dap_param_to_set_control_put),
-};
-
-static const struct snd_kcontrol_new dolby_dap_param_to_get_controls[] = {
- SOC_SINGLE_MULTI_EXT("DS1 DAP Get Param", SND_SOC_NOPM, 0, 0xFFFFFFFF,
- 0, 128, msm_dolby_dap_param_to_get_control_get,
- msm_dolby_dap_param_to_get_control_put),
-};
-
-static const struct snd_kcontrol_new dolby_dap_param_visualizer_controls[] = {
- SOC_SINGLE_MULTI_EXT("DS1 DAP Get Visualizer", SND_SOC_NOPM, 0,
- 0xFFFFFFFF, 0, 41, msm_dolby_dap_param_visualizer_control_get,
- msm_dolby_dap_param_visualizer_control_put),
-};
-
-static const struct snd_kcontrol_new dolby_dap_param_end_point_controls[] = {
- SOC_SINGLE_MULTI_EXT("DS1 DAP Endpoint", SND_SOC_NOPM, 0,
- 0xFFFFFFFF, 0, 1, msm_dolby_dap_endpoint_control_get,
- msm_dolby_dap_endpoint_control_put),
-};
-
-void msm_dolby_dap_add_controls(struct snd_soc_platform *platform)
-{
- snd_soc_add_platform_controls(platform,
- dolby_license_controls,
- ARRAY_SIZE(dolby_license_controls));
-
- snd_soc_add_platform_controls(platform,
- dolby_security_controls,
- ARRAY_SIZE(dolby_security_controls));
-
- snd_soc_add_platform_controls(platform,
- dolby_dap_param_to_set_controls,
- ARRAY_SIZE(dolby_dap_param_to_set_controls));
-
- snd_soc_add_platform_controls(platform,
- dolby_dap_param_to_get_controls,
- ARRAY_SIZE(dolby_dap_param_to_get_controls));
-
- snd_soc_add_platform_controls(platform,
- dolby_dap_param_visualizer_controls,
- ARRAY_SIZE(dolby_dap_param_visualizer_controls));
-
- snd_soc_add_platform_controls(platform,
- dolby_dap_param_end_point_controls,
- ARRAY_SIZE(dolby_dap_param_end_point_controls));
-}
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index bc1d21a826b5..fcff383b9c3b 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -1303,13 +1303,22 @@ static struct cal_block_data *afe_find_cal_topo_id_by_port(
MSM_AFE_PORT_TYPE_TX)?(TX_DEVICE):(RX_DEVICE));
afe_top =
(struct audio_cal_info_afe_top *)cal_block->cal_info;
- if ((afe_top->path == path) &&
- (afe_top->acdb_id ==
- this_afe.dev_acdb_id[afe_port_index])) {
- pr_debug("%s: top_id:%x acdb_id:%d afe_port:%d\n",
+ if (afe_top->path == path) {
+ if (this_afe.dev_acdb_id[afe_port_index] > 0) {
+ if (afe_top->acdb_id ==
+ this_afe.dev_acdb_id[afe_port_index]) {
+ pr_debug("%s: top_id:%x acdb_id:%d afe_port_id:%d\n",
+ __func__, afe_top->topology,
+ afe_top->acdb_id,
+ q6audio_get_port_id(port_id));
+ return cal_block;
+ }
+ } else {
+ pr_debug("%s: top_id:%x acdb_id:%d afe_port:%d\n",
__func__, afe_top->topology, afe_top->acdb_id,
q6audio_get_port_id(port_id));
- return cal_block;
+ return cal_block;
+ }
}
}
@@ -1497,6 +1506,8 @@ static void send_afe_cal_type(int cal_index, int port_id)
{
struct cal_block_data *cal_block = NULL;
int ret;
+ int afe_port_index = q6audio_get_port_index(port_id);
+
pr_debug("%s:\n", __func__);
if (this_afe.cal_data[cal_index] == NULL) {
@@ -1505,10 +1516,17 @@ static void send_afe_cal_type(int cal_index, int port_id)
goto done;
}
+ if (afe_port_index < 0) {
+ pr_err("%s: Error getting AFE port index %d\n",
+ __func__, afe_port_index);
+ goto done;
+ }
+
mutex_lock(&this_afe.cal_data[cal_index]->lock);
- if ((cal_index == AFE_COMMON_RX_CAL) ||
- (cal_index == AFE_COMMON_TX_CAL))
+ if (((cal_index == AFE_COMMON_RX_CAL) ||
+ (cal_index == AFE_COMMON_TX_CAL)) &&
+ (this_afe.dev_acdb_id[afe_port_index] > 0))
cal_block = afe_find_cal(cal_index, port_id);
else
cal_block = cal_utils_get_only_cal_block(