diff options
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(¬ifier_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( |
