diff options
46 files changed, 1326 insertions, 126 deletions
diff --git a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt index 421379116989..808e18b495d5 100644 --- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt +++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt @@ -63,6 +63,14 @@ First Level Node - FG Gen3 device Definition: The voltage threshold (in mV) which upon set will be used for configuring the low battery voltage threshold. +- qcom,fg-recharge-voltage + Usage: optional + Value type: <u32> + Definition: The voltage threshold (in mV) based on which the charging + will be resumed once the charging is complete. If this + property is not specified, then the default value will be + 4250mV. + - qcom,fg-chg-term-current Usage: optional Value type: <u32> diff --git a/arch/arm/boot/dts/qcom/fg-gen3-batterydata-demo-6000mah.dtsi b/arch/arm/boot/dts/qcom/fg-gen3-batterydata-demo-6000mah.dtsi new file mode 100644 index 000000000000..b107918a8e98 --- /dev/null +++ b/arch/arm/boot/dts/qcom/fg-gen3-batterydata-demo-6000mah.dtsi @@ -0,0 +1,78 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +qcom,demo_6000mah { + qcom,max-voltage-uv = <4350000>; + qcom,fg-cc-cv-threshold-mv = <4340>; + qcom,nom-batt-capacity-mah = <6000>; + qcom,batt-id-kohm = <75>; + qcom,battery-beta = <3435>; + qcom,battery-type = "Demo_battery_6000mah"; + qcom,fg-profile-data = [ + 2C 1F 3F FC + E9 03 A1 FD + 58 1D FD F5 + 27 12 2C 14 + 3F 18 FF 22 + 9B 45 A3 52 + 55 00 00 00 + 0E 00 00 00 + 00 00 1C AC + F7 CD 71 B5 + 1A 00 0C 00 + 3C EB 54 E4 + EC 05 7F FA + 76 05 F5 02 + CA F3 82 3A + 2A 09 40 40 + 07 00 05 00 + 58 1F 42 06 + 85 03 35 F4 + 4D 1D 37 F2 + 23 0A 79 15 + B7 18 32 23 + 26 45 72 53 + 55 00 00 00 + 0D 00 00 00 + 00 00 13 CC + 03 00 98 BD + 16 00 00 00 + 3C EB 54 E4 + 9F FC A3 F3 + 0F FC DF FA + FF E5 A9 23 + CB 33 08 33 + 07 10 00 00 + 81 0D 99 45 + 16 00 19 00 + 75 01 0A FA + FF 00 00 00 + 00 00 00 00 + 00 00 00 00 + 00 00 00 00 + 00 00 00 00 + 00 00 00 00 + 00 00 00 00 + 00 00 00 00 + 00 00 00 00 + 00 00 00 00 + 00 00 00 00 + 00 00 00 00 + 00 00 00 00 + 00 00 00 00 + 00 00 00 00 + 00 00 00 00 + 00 00 00 00 + 00 00 00 00 + 00 00 00 00 + ]; +}; diff --git a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-qrd-vr1.dtsi b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-qrd-vr1.dtsi index a56e9836784c..14567c3b5010 100644 --- a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-qrd-vr1.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-qrd-vr1.dtsi @@ -220,6 +220,7 @@ cell-index = <0>; compatible = "qcom,camera"; reg = <0x0>; + qcom,special-support-sensors = "imx362_gt24c64a"; qcom,csiphy-sd-index = <0>; qcom,csid-sd-index = <0>; qcom,mount-angle = <270>; diff --git a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-skuk.dtsi b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-skuk.dtsi index da568fd8979c..36441f9aa15a 100644 --- a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-skuk.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-skuk.dtsi @@ -184,6 +184,8 @@ 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,eeprom-src = <&eeprom0>; cam_vio-supply = <&pm8998_lvs1>; cam_vana-supply = <&pmi8998_bob>; diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-cdp.dtsi new file mode 100644 index 000000000000..3ef09569a430 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-cdp.dtsi @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + qcom,csiphy@ca34000 { + qcom,clock-rates = <0 0 0 0 0 0 384000000 0 0 269333333 0 + 0 384000000 0>; + }; + + qcom,csiphy@ca35000 { + qcom,clock-rates = <0 0 0 0 0 0 384000000 0 0 269333333 0 + 0 384000000 0>; + }; + + qcom,csiphy@ca36000 { + qcom,clock-rates = <0 0 0 0 0 0 384000000 0 0 269333333 0 + 0 384000000 0>; + }; + + qcom,csid@ca30000 { + qcom,csi-vdd-voltage = <1225000>; + qcom,mipi-csi-vdd-supply = <&pmfalcon_l1>; + gdscr-supply = <&gdsc_camss_top>; + vdd_sec-supply = <&pm2falcon_l1>; + bimc_smmu-supply = <&gdsc_bimc_smmu>; + qcom,cam-vreg-name = "vdd_sec", "gdscr", "bimc_smmu"; + qcom,clock-rates = <0 0 0 0 0 0 0 384000000 384000000 + 0 0 0 0 0>; + }; + + qcom,csid@ca30400 { + qcom,csi-vdd-voltage = <1225000>; + qcom,mipi-csi-vdd-supply = <&pmfalcon_l1>; + gdscr-supply = <&gdsc_camss_top>; + vdd_sec-supply = <&pm2falcon_l1>; + bimc_smmu-supply = <&gdsc_bimc_smmu>; + qcom,cam-vreg-name = "vdd_sec", "gdscr", "bimc_smmu"; + qcom,clock-rates = <0 0 0 0 0 0 0 384000000 384000000 + 0 0 0 0 0>; + }; + + qcom,csid@ca30800 { + qcom,csi-vdd-voltage = <1225000>; + qcom,mipi-csi-vdd-supply = <&pmfalcon_l1>; + gdscr-supply = <&gdsc_camss_top>; + vdd_sec-supply = <&pm2falcon_l1>; + bimc_smmu-supply = <&gdsc_bimc_smmu>; + qcom,cam-vreg-name = "vdd_sec", "gdscr", "bimc_smmu"; + qcom,clock-rates = <0 0 0 0 0 0 0 384000000 384000000 + 0 0 0 0 0>; + }; + + qcom,csid@ca30c00 { + qcom,csi-vdd-voltage = <1225000>; + qcom,mipi-csi-vdd-supply = <&pmfalcon_l1>; + gdscr-supply = <&gdsc_camss_top>; + vdd_sec-supply = <&pm2falcon_l1>; + bimc_smmu-supply = <&gdsc_bimc_smmu>; + qcom,cam-vreg-name = "vdd_sec", "gdscr", "bimc_smmu"; + qcom,clock-rates = <0 0 0 0 0 0 0 384000000 384000000 + 0 0 0 0 0>; + }; +}; + +&cci { + actuator0: qcom,actuator@0 { + cell-index = <0>; + reg = <0x0>; + compatible = "qcom,actuator"; + qcom,cci-master = <0>; + gpios = <&tlmm 27 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>; + }; + + actuator1: qcom,actuator@1 { + cell-index = <1>; + reg = <0x1>; + compatible = "qcom,actuator"; + qcom,cci-master = <1>; + gpios = <&tlmm 27 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>; + }; + + ois0: qcom,ois@0 { + cell-index = <0>; + reg = <0x0>; + compatible = "qcom,ois"; + qcom,cci-master = <0>; + gpios = <&tlmm 27 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 = <&pmfalcon_l11>; + cam_vana-supply = <&pm2falcon_bob>; + cam_vdig-supply = <&pmfalcon_s5>; + qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig"; + qcom,cam-vreg-min-voltage = <0 3300000 1350000>; + qcom,cam-vreg-max-voltage = <0 3600000 1350000>; + qcom,cam-vreg-op-mode = <0 80000 105000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_rear_active + &cam_actuator_vaf_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_rear_suspend + &cam_actuator_vaf_suspend>; + gpios = <&tlmm 13 0>, + <&tlmm 30 0>, + <&pmfalcon_gpios 4 0>, + <&tlmm 29 0>, + <&tlmm 27 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vdig = <2>; + qcom,gpio-vana = <3>; + qcom,gpio-vaf = <4>; + qcom,gpio-req-tbl-num = <0 1 2 3 4>; + qcom,gpio-req-tbl-flags = <1 0 0 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_VDIG", + "CAM_VANA", + "CAM_VAF"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <0>; + status = "ok"; + clocks = <&clock_mmss clk_mclk0_clk_src>, + <&clock_mmss clk_mmss_camss_mclk0_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,actuator-src = <&actuator0>; + qcom,ois-src = <&ois0>; + qcom,eeprom-src = <&eeprom0>; + cam_vio-supply = <&pmfalcon_l11>; + cam_vana-supply = <&pm2falcon_bob>; + cam_vdig-supply = <&pmfalcon_s5>; + qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig"; + qcom,cam-vreg-min-voltage = <0 3300000 1350000>; + qcom,cam-vreg-max-voltage = <0 3600000 1350000>; + qcom,cam-vreg-op-mode = <0 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 13 0>, + <&tlmm 30 0>, + <&pmfalcon_gpios 4 0>, + <&tlmm 29 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 clk_mclk0_clk_src>, + <&clock_mmss clk_mmss_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; +}; + +&pmfalcon_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"; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi new file mode 100644 index 000000000000..3ef09569a430 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + qcom,csiphy@ca34000 { + qcom,clock-rates = <0 0 0 0 0 0 384000000 0 0 269333333 0 + 0 384000000 0>; + }; + + qcom,csiphy@ca35000 { + qcom,clock-rates = <0 0 0 0 0 0 384000000 0 0 269333333 0 + 0 384000000 0>; + }; + + qcom,csiphy@ca36000 { + qcom,clock-rates = <0 0 0 0 0 0 384000000 0 0 269333333 0 + 0 384000000 0>; + }; + + qcom,csid@ca30000 { + qcom,csi-vdd-voltage = <1225000>; + qcom,mipi-csi-vdd-supply = <&pmfalcon_l1>; + gdscr-supply = <&gdsc_camss_top>; + vdd_sec-supply = <&pm2falcon_l1>; + bimc_smmu-supply = <&gdsc_bimc_smmu>; + qcom,cam-vreg-name = "vdd_sec", "gdscr", "bimc_smmu"; + qcom,clock-rates = <0 0 0 0 0 0 0 384000000 384000000 + 0 0 0 0 0>; + }; + + qcom,csid@ca30400 { + qcom,csi-vdd-voltage = <1225000>; + qcom,mipi-csi-vdd-supply = <&pmfalcon_l1>; + gdscr-supply = <&gdsc_camss_top>; + vdd_sec-supply = <&pm2falcon_l1>; + bimc_smmu-supply = <&gdsc_bimc_smmu>; + qcom,cam-vreg-name = "vdd_sec", "gdscr", "bimc_smmu"; + qcom,clock-rates = <0 0 0 0 0 0 0 384000000 384000000 + 0 0 0 0 0>; + }; + + qcom,csid@ca30800 { + qcom,csi-vdd-voltage = <1225000>; + qcom,mipi-csi-vdd-supply = <&pmfalcon_l1>; + gdscr-supply = <&gdsc_camss_top>; + vdd_sec-supply = <&pm2falcon_l1>; + bimc_smmu-supply = <&gdsc_bimc_smmu>; + qcom,cam-vreg-name = "vdd_sec", "gdscr", "bimc_smmu"; + qcom,clock-rates = <0 0 0 0 0 0 0 384000000 384000000 + 0 0 0 0 0>; + }; + + qcom,csid@ca30c00 { + qcom,csi-vdd-voltage = <1225000>; + qcom,mipi-csi-vdd-supply = <&pmfalcon_l1>; + gdscr-supply = <&gdsc_camss_top>; + vdd_sec-supply = <&pm2falcon_l1>; + bimc_smmu-supply = <&gdsc_bimc_smmu>; + qcom,cam-vreg-name = "vdd_sec", "gdscr", "bimc_smmu"; + qcom,clock-rates = <0 0 0 0 0 0 0 384000000 384000000 + 0 0 0 0 0>; + }; +}; + +&cci { + actuator0: qcom,actuator@0 { + cell-index = <0>; + reg = <0x0>; + compatible = "qcom,actuator"; + qcom,cci-master = <0>; + gpios = <&tlmm 27 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>; + }; + + actuator1: qcom,actuator@1 { + cell-index = <1>; + reg = <0x1>; + compatible = "qcom,actuator"; + qcom,cci-master = <1>; + gpios = <&tlmm 27 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>; + }; + + ois0: qcom,ois@0 { + cell-index = <0>; + reg = <0x0>; + compatible = "qcom,ois"; + qcom,cci-master = <0>; + gpios = <&tlmm 27 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 = <&pmfalcon_l11>; + cam_vana-supply = <&pm2falcon_bob>; + cam_vdig-supply = <&pmfalcon_s5>; + qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig"; + qcom,cam-vreg-min-voltage = <0 3300000 1350000>; + qcom,cam-vreg-max-voltage = <0 3600000 1350000>; + qcom,cam-vreg-op-mode = <0 80000 105000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_rear_active + &cam_actuator_vaf_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_rear_suspend + &cam_actuator_vaf_suspend>; + gpios = <&tlmm 13 0>, + <&tlmm 30 0>, + <&pmfalcon_gpios 4 0>, + <&tlmm 29 0>, + <&tlmm 27 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vdig = <2>; + qcom,gpio-vana = <3>; + qcom,gpio-vaf = <4>; + qcom,gpio-req-tbl-num = <0 1 2 3 4>; + qcom,gpio-req-tbl-flags = <1 0 0 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_VDIG", + "CAM_VANA", + "CAM_VAF"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <0>; + status = "ok"; + clocks = <&clock_mmss clk_mclk0_clk_src>, + <&clock_mmss clk_mmss_camss_mclk0_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,actuator-src = <&actuator0>; + qcom,ois-src = <&ois0>; + qcom,eeprom-src = <&eeprom0>; + cam_vio-supply = <&pmfalcon_l11>; + cam_vana-supply = <&pm2falcon_bob>; + cam_vdig-supply = <&pmfalcon_s5>; + qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig"; + qcom,cam-vreg-min-voltage = <0 3300000 1350000>; + qcom,cam-vreg-max-voltage = <0 3600000 1350000>; + qcom,cam-vreg-op-mode = <0 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 13 0>, + <&tlmm 30 0>, + <&pmfalcon_gpios 4 0>, + <&tlmm 29 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 clk_mclk0_clk_src>, + <&clock_mmss clk_mmss_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; +}; + +&pmfalcon_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"; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-pmfalcon.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-pmfalcon.dtsi index e83191ebfbc0..54a2a4a00dc0 100644 --- a/arch/arm/boot/dts/qcom/msm8998-interposer-pmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-interposer-pmfalcon.dtsi @@ -45,12 +45,6 @@ /delete-property/qcom,switch-source; }; -&eeprom0 { - /delete-property/cam_vio-supply; - /delete-property/cam_vana-supply; - /delete-property/cam_vdig-supply; - /delete-property/gpios; -}; &eeprom1 { /delete-property/cam_vio-supply; @@ -66,7 +60,6 @@ }; &cci { - /delete-node/qcom,camera@0; /delete-node/qcom,camera@1; /delete-node/qcom,camera@2; @@ -220,10 +213,6 @@ }; &soc { - /delete-node/qcom,csid@ca30000; - /delete-node/qcom,csid@ca30400; - /delete-node/qcom,csid@ca30800; - /delete-node/qcom,csid@ca30c00; /delete-node/gpio_keys; /delete-node/qcom,lpass@17300000; /delete-node/qcom,mss@4080000; diff --git a/arch/arm/boot/dts/qcom/msm8998-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8998-mtp.dtsi index 76124833dc36..45d6398daf25 100644 --- a/arch/arm/boot/dts/qcom/msm8998-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-mtp.dtsi @@ -623,5 +623,6 @@ qcom,batt-id-range-pct = <15>; #include "fg-gen3-batterydata-itech-3000mah.dtsi" #include "fg-gen3-batterydata-ascent-3450mah.dtsi" + #include "fg-gen3-batterydata-demo-6000mah.dtsi" }; }; diff --git a/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-cdp.dts b/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-cdp.dts index 528e48df1268..bb7046ab58cb 100644 --- a/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-cdp.dts +++ b/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-cdp.dts @@ -17,6 +17,7 @@ #include "msm8998-interposer-msmfalcon-cdp.dtsi" #include "msm8998-interposer-pmfalcon.dtsi" #include "msm8998-interposer-msmfalcon-audio.dtsi" +#include "msm8998-interposer-camera-sensor-cdp.dtsi" / { model = "Qualcomm Technologies, Inc. MSM 8998 v2.1 MSM FALCON Interposer CDP"; diff --git a/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-mtp.dts b/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-mtp.dts index 0f0a88b33402..166e09577d46 100644 --- a/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-mtp.dts +++ b/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-mtp.dts @@ -17,6 +17,7 @@ #include "msm8998-interposer-msmfalcon-mtp.dtsi" #include "msm8998-interposer-pmfalcon.dtsi" #include "msm8998-interposer-msmfalcon-audio.dtsi" +#include "msm8998-interposer-camera-sensor-mtp.dtsi" / { model = "Qualcomm Technologies, Inc. MSM 8998 v2.1 MSM FALCON Interposer MTP"; diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi index ed8bee03b4d0..79cdc2b701e1 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi @@ -48,6 +48,7 @@ reg = <0x0 0x0>; enable-method = "psci"; qcom,limits-info = <&mitigation_profile0>; + qcom,ea = <&ea0>; }; CPU1: cpu@1 { @@ -56,6 +57,7 @@ reg = <0x0 0x1>; enable-method = "psci"; qcom,limits-info = <&mitigation_profile0>; + qcom,ea = <&ea1>; }; CPU2: cpu@2 { @@ -64,6 +66,7 @@ reg = <0x0 0x2>; enable-method = "psci"; qcom,limits-info = <&mitigation_profile0>; + qcom,ea = <&ea2>; }; CPU3: cpu@3 { @@ -72,6 +75,7 @@ reg = <0x0 0x3>; enable-method = "psci"; qcom,limits-info = <&mitigation_profile0>; + qcom,ea = <&ea3>; }; CPU4: cpu@100 { @@ -80,6 +84,7 @@ reg = <0x0 0x100>; enable-method = "psci"; qcom,limits-info = <&mitigation_profile1>; + qcom,ea = <&ea4>; }; CPU5: cpu@101 { @@ -88,6 +93,7 @@ reg = <0x0 0x101>; enable-method = "psci"; qcom,limits-info = <&mitigation_profile2>; + qcom,ea = <&ea5>; }; CPU6: cpu@102 { @@ -96,6 +102,7 @@ reg = <0x0 0x102>; enable-method = "psci"; qcom,limits-info = <&mitigation_profile3>; + qcom,ea = <&ea6>; }; CPU7: cpu@103 { @@ -104,6 +111,7 @@ reg = <0x0 0x103>; enable-method = "psci"; qcom,limits-info = <&mitigation_profile4>; + qcom,ea = <&ea7>; }; cpu-map { @@ -540,6 +548,45 @@ }; }; + qcom,msm-core@780000 { + compatible = "qcom,apss-core-ea"; + reg = <0x780000 0x1000>; + qcom,low-hyst-temp = <10>; + qcom,high-hyst-temp = <5>; + + ea0: ea0 { + sensor = <&sensor_information1>; + }; + + ea1: ea1 { + sensor = <&sensor_information1>; + }; + + ea2: ea2 { + sensor = <&sensor_information1>; + }; + + ea3: ea3 { + sensor = <&sensor_information1>; + }; + + ea4: ea4 { + sensor = <&sensor_information3>; + }; + + ea5: ea5 { + sensor = <&sensor_information4>; + }; + + ea6: ea6 { + sensor = <&sensor_information5>; + }; + + ea7: ea7 { + sensor = <&sensor_information6>; + }; + }; + uartblsp2dm1: serial@0c1b0000 { compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; reg = <0xc1b0000 0x1000>; @@ -1206,6 +1253,34 @@ qcom,irq-is-percpu; interrupts = <1 6 4>; }; + + qcom_seecom: qseecom@86d00000 { + compatible = "qcom,qseecom"; + reg = <0x86d00000 0x2200000>; + reg-names = "secapp-region"; + qcom,hlos-num-ce-hw-instances = <1>; + qcom,hlos-ce-hw-instance = <0>; + qcom,qsee-ce-hw-instance = <0>; + qcom,disk-encrypt-pipe-pair = <2>; + qcom,support-fde; + qcom,no-clock-support; + qcom,msm-bus,name = "qseecom-noc"; + qcom,msm-bus,num-cases = <4>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <55 512 0 0>, + <55 512 200000 400000>, + <55 512 300000 800000>, + <55 512 400000 1000000>; + clock-names = "core_clk_src", "core_clk", + "iface_clk", "bus_clk"; + clocks = <&clock_gcc QSEECOM_CE1_CLK>, + <&clock_gcc QSEECOM_CE1_CLK>, + <&clock_gcc QSEECOM_CE1_CLK>, + <&clock_gcc QSEECOM_CE1_CLK>; + qcom,ce-opp-freq = <171430000>; + qcom,qsee-reentrancy-support = <2>; + }; }; #include "msmfalcon-ion.dtsi" diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index b42b68482279..c1865f9ee8b3 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3128,8 +3128,13 @@ static int __clk_init(struct device *dev, struct clk *clk_user) core->ops->init(core->hw); if (core->flags & CLK_IS_CRITICAL) { + unsigned long flags; + clk_core_prepare(core); + + flags = clk_enable_lock(); clk_core_enable(core); + clk_enable_unlock(flags); } kref_init(&core->ref); @@ -3864,6 +3869,41 @@ static int parent_ready(struct device_node *np) } /** + * of_clk_detect_critical() - set CLK_IS_CRITICAL flag from Device Tree + * @np: Device node pointer associated with clock provider + * @index: clock index + * @flags: pointer to clk_core->flags + * + * Detects if the clock-critical property exists and, if so, sets the + * corresponding CLK_IS_CRITICAL flag. + * + * Do not use this function. It exists only for legacy Device Tree + * bindings, such as the one-clock-per-node style that are outdated. + * Those bindings typically put all clock data into .dts and the Linux + * driver has no clock data, thus making it impossible to set this flag + * correctly from the driver. Only those drivers may call + * of_clk_detect_critical from their setup functions. + * + * Return: error code or zero on success + */ +int of_clk_detect_critical(struct device_node *np, + int index, unsigned long *flags) +{ + struct property *prop; + const __be32 *cur; + uint32_t idx; + + if (!np || !flags) + return -EINVAL; + + of_property_for_each_u32(np, "clock-critical", prop, cur, idx) + if (index == idx) + *flags |= CLK_IS_CRITICAL; + + return 0; +} + +/** * of_clk_init() - Scan and init clock providers from the DT * @matches: array of compatible values and init functions for providers. * diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c index 55c043b44cea..0bef7effe601 100644 --- a/drivers/crypto/msm/qce50.c +++ b/drivers/crypto/msm/qce50.c @@ -1347,7 +1347,8 @@ go_proc: CRYPTO_CONFIG_REG)); /* issue go to crypto */ if (use_hw_key == false) { - QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), pce_dev->iobase + CRYPTO_GOPROC_REG); } else { QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), @@ -1528,7 +1529,8 @@ static int _ce_setup_aead_direct(struct qce_device *pce_dev, CRYPTO_CONFIG_REG)); /* issue go to crypto */ - QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), pce_dev->iobase + CRYPTO_GOPROC_REG); /* * Ensure previous instructions (setting the GO register) @@ -1847,7 +1849,8 @@ static int _ce_setup_cipher_direct(struct qce_device *pce_dev, CRYPTO_CONFIG_REG)); /* issue go to crypto */ if (use_hw_key == false) { - QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), pce_dev->iobase + CRYPTO_GOPROC_REG); } else { QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), @@ -1935,7 +1938,8 @@ static int _ce_f9_setup_direct(struct qce_device *pce_dev, QCE_WRITE_REG(pce_dev->reg.crypto_cfg_le, (pce_dev->iobase + CRYPTO_CONFIG_REG)); /* write go */ - QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), pce_dev->iobase + CRYPTO_GOPROC_REG); /* * Ensure previous instructions (setting the GO register) @@ -2012,7 +2016,8 @@ static int _ce_f8_setup_direct(struct qce_device *pce_dev, QCE_WRITE_REG(pce_dev->reg.crypto_cfg_le, (pce_dev->iobase + CRYPTO_CONFIG_REG)); /* write go */ - QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), pce_dev->iobase + CRYPTO_GOPROC_REG); /* * Ensure previous instructions (setting the GO register) @@ -3336,8 +3341,8 @@ static int _setup_cipher_aes_cmdlistptrs(struct qce_device *pdev, int cri_index, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -3450,8 +3455,8 @@ static int _setup_cipher_des_cmdlistptrs(struct qce_device *pdev, int cri_index, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -3494,8 +3499,8 @@ static int _setup_cipher_null_cmdlistptrs(struct qce_device *pdev, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -3672,8 +3677,8 @@ static int _setup_auth_cmdlistptrs(struct qce_device *pdev, int cri_index, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -3889,8 +3894,8 @@ static int _setup_aead_cmdlistptrs(struct qce_device *pdev, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -4022,8 +4027,8 @@ static int _setup_aead_ccm_cmdlistptrs(struct qce_device *pdev, int cri_index, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -4108,8 +4113,8 @@ static int _setup_f8_cmdlistptrs(struct qce_device *pdev, int cri_index, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; @@ -4190,8 +4195,8 @@ static int _setup_f9_cmdlistptrs(struct qce_device *pdev, int cri_index, pdev->reg.crypto_cfg_le, NULL); qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, - ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), - &pcl_info->go_proc); + ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | + (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; *pvaddr = (unsigned char *) ce_vaddr; diff --git a/drivers/gpu/msm/adreno_a5xx_preempt.c b/drivers/gpu/msm/adreno_a5xx_preempt.c index 09c550c9f58c..0e56731b16e2 100644 --- a/drivers/gpu/msm/adreno_a5xx_preempt.c +++ b/drivers/gpu/msm/adreno_a5xx_preempt.c @@ -22,7 +22,7 @@ #define PREEMPT_SMMU_RECORD(_field) \ offsetof(struct a5xx_cp_smmu_info, _field) -static void _update_wptr(struct adreno_device *adreno_dev) +static void _update_wptr(struct adreno_device *adreno_dev, bool reset_timer) { struct adreno_ringbuffer *rb = adreno_dev->cur_rb; unsigned int wptr; @@ -35,10 +35,16 @@ static void _update_wptr(struct adreno_device *adreno_dev) if (wptr != rb->wptr) { adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_WPTR, rb->wptr); + /* + * In case something got submitted while preemption was on + * going, reset the timer. + */ + reset_timer = 1; + } + if (reset_timer) rb->dispatch_q.expires = jiffies + msecs_to_jiffies(adreno_drawobj_timeout); - } spin_unlock_irqrestore(&rb->preempt_lock, flags); } @@ -90,7 +96,7 @@ static void _a5xx_preemption_done(struct adreno_device *adreno_dev) adreno_dev->next_rb = NULL; /* Update the wptr for the new command queue */ - _update_wptr(adreno_dev); + _update_wptr(adreno_dev, true); /* Update the dispatcher timer for the new command queue */ mod_timer(&adreno_dev->dispatcher.timer, @@ -213,7 +219,7 @@ void a5xx_preemption_trigger(struct adreno_device *adreno_dev) */ if (next != NULL) { - _update_wptr(adreno_dev); + _update_wptr(adreno_dev, false); mod_timer(&adreno_dev->dispatcher.timer, adreno_dev->cur_rb->dispatch_q.expires); @@ -304,7 +310,7 @@ void a5xx_preempt_callback(struct adreno_device *adreno_dev, int bit) adreno_dev->next_rb = NULL; /* Update the wptr if it changed while preemption was ongoing */ - _update_wptr(adreno_dev); + _update_wptr(adreno_dev, true); /* Update the dispatcher timer for the new command queue */ mod_timer(&adreno_dev->dispatcher.timer, diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c index f001706236ab..0ec16e606545 100644 --- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c +++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c @@ -358,6 +358,7 @@ static struct device_attribute attrs[] = { static struct synaptics_rmi4_fwu_handle *fwu; DECLARE_COMPLETION(fwu_dsx_remove_complete); +DEFINE_MUTEX(dsx_fwu_sysfs_mutex); static unsigned int extract_uint_le(const unsigned char *ptr) { @@ -1589,28 +1590,49 @@ static ssize_t fwu_sysfs_show_image(struct file *data_file, char *buf, loff_t pos, size_t count) { struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + ssize_t retval; + + if (!mutex_trylock(&dsx_fwu_sysfs_mutex)) + return -EBUSY; if (count < fwu->config_size) { dev_err(rmi4_data->pdev->dev.parent, "%s: Not enough space (%zu bytes) in buffer\n", __func__, count); - return -EINVAL; + retval = -EINVAL; + goto show_image_exit; } memcpy(buf, fwu->read_config_buf, fwu->config_size); - - return fwu->config_size; + retval = fwu->config_size; +show_image_exit: + mutex_unlock(&dsx_fwu_sysfs_mutex); + return retval; } static ssize_t fwu_sysfs_store_image(struct file *data_file, struct kobject *kobj, struct bin_attribute *attributes, char *buf, loff_t pos, size_t count) { + ssize_t retval; + + if (!mutex_trylock(&dsx_fwu_sysfs_mutex)) + return -EBUSY; + if (count > (fwu->image_size - fwu->data_pos)) { dev_err(fwu->rmi4_data->pdev->dev.parent, "%s: Not enough space in buffer\n", __func__); - return -EINVAL; + retval = -EINVAL; + goto exit; + } + + if (!fwu->ext_data_source) { + dev_err(fwu->rmi4_data->pdev->dev.parent, + "%s: Need to set imagesize\n", + __func__); + retval = -EINVAL; + goto exit; } memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]), @@ -1619,16 +1641,21 @@ static ssize_t fwu_sysfs_store_image(struct file *data_file, fwu->data_pos += count; +exit: + mutex_unlock(&dsx_fwu_sysfs_mutex); return count; } static ssize_t fwu_sysfs_force_reflash_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - int retval; + ssize_t retval; unsigned int input; struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + if (!mutex_trylock(&dsx_fwu_sysfs_mutex)) + return -EBUSY; + if (sscanf(buf, "%u", &input) != 1) { retval = -EINVAL; goto exit; @@ -1657,6 +1684,9 @@ exit: fwu->ext_data_source = NULL; fwu->force_update = FORCE_UPDATE; fwu->do_lockdown = DO_LOCKDOWN; + fwu->data_pos = 0; + fwu->image_size = 0; + mutex_unlock(&dsx_fwu_sysfs_mutex); return retval; } @@ -1667,6 +1697,9 @@ static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, unsigned int input; struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + if (!mutex_trylock(&dsx_fwu_sysfs_mutex)) + return -EBUSY; + if (sscanf(buf, "%u", &input) != 1) { retval = -EINVAL; goto exit; @@ -1700,6 +1733,9 @@ exit: fwu->ext_data_source = NULL; fwu->force_update = FORCE_UPDATE; fwu->do_lockdown = DO_LOCKDOWN; + fwu->data_pos = 0; + fwu->image_size = 0; + mutex_unlock(&dsx_fwu_sysfs_mutex); return retval; } @@ -1710,6 +1746,9 @@ static ssize_t fwu_sysfs_write_config_store(struct device *dev, unsigned int input; struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + if (!mutex_trylock(&dsx_fwu_sysfs_mutex)) + return -EBUSY; + if (sscanf(buf, "%u", &input) != 1) { retval = -EINVAL; goto exit; @@ -1733,6 +1772,9 @@ static ssize_t fwu_sysfs_write_config_store(struct device *dev, exit: kfree(fwu->ext_data_source); fwu->ext_data_source = NULL; + fwu->data_pos = 0; + fwu->image_size = 0; + mutex_unlock(&dsx_fwu_sysfs_mutex); return retval; } @@ -1749,7 +1791,11 @@ static ssize_t fwu_sysfs_read_config_store(struct device *dev, if (input != 1) return -EINVAL; + if (!mutex_trylock(&dsx_fwu_sysfs_mutex)) + return -EBUSY; retval = fwu_do_read_config(); + mutex_unlock(&dsx_fwu_sysfs_mutex); + if (retval < 0) { dev_err(rmi4_data->pdev->dev.parent, "%s: Failed to read config\n", @@ -1770,7 +1816,10 @@ static ssize_t fwu_sysfs_config_area_store(struct device *dev, if (retval) return retval; + if (!mutex_trylock(&dsx_fwu_sysfs_mutex)) + return -EBUSY; fwu->config_area = config_area; + mutex_unlock(&dsx_fwu_sysfs_mutex); return count; } @@ -1778,17 +1827,30 @@ static ssize_t fwu_sysfs_config_area_store(struct device *dev, static ssize_t fwu_sysfs_image_name_show(struct device *dev, struct device_attribute *attr, char *buf) { + ssize_t retval; + + if (!mutex_trylock(&dsx_fwu_sysfs_mutex)) + return -EBUSY; if (strnlen(fwu->rmi4_data->fw_name, SYNA_FW_NAME_MAX_LEN) > 0) - return snprintf(buf, PAGE_SIZE, "%s\n", + retval = snprintf(buf, PAGE_SIZE, "%s\n", fwu->rmi4_data->fw_name); else - return snprintf(buf, PAGE_SIZE, "No firmware name given\n"); + retval = snprintf(buf, PAGE_SIZE, "No firmware name given\n"); + mutex_unlock(&dsx_fwu_sysfs_mutex); + return retval; } static ssize_t fwu_sysfs_image_name_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - if (sscanf(buf, "%s", fwu->image_name) != 1) + ssize_t retval; + + if (!mutex_trylock(&dsx_fwu_sysfs_mutex)) + return -EBUSY; + retval = sscanf(buf, "%49s", fwu->image_name); + mutex_unlock(&dsx_fwu_sysfs_mutex); + + if (retval != 1) return -EINVAL; return count; @@ -1801,9 +1863,12 @@ static ssize_t fwu_sysfs_image_size_store(struct device *dev, unsigned long size; struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + if (!mutex_trylock(&dsx_fwu_sysfs_mutex)) + return -EBUSY; + retval = sstrtoul(buf, 10, &size); if (retval) - return retval; + goto exit; fwu->image_size = size; fwu->data_pos = 0; @@ -1814,10 +1879,14 @@ static ssize_t fwu_sysfs_image_size_store(struct device *dev, dev_err(rmi4_data->pdev->dev.parent, "%s: Failed to alloc mem for image data\n", __func__); - return -ENOMEM; + retval = -ENOMEM; + goto exit; } - return count; + retval = count; +exit: + mutex_unlock(&dsx_fwu_sysfs_mutex); + return retval; } static ssize_t fwu_sysfs_block_size_show(struct device *dev, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h index 3b6a2eecb4b6..13a7a398759b 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h @@ -243,6 +243,8 @@ struct msm_vfe_core_ops { bool (*is_module_cfg_lock_needed)(uint32_t reg_offset); int (*ahb_clk_cfg)(struct vfe_device *vfe_dev, struct msm_isp_ahb_clk_cfg *ahb_cfg); + int (*start_fetch_eng_multi_pass)(struct vfe_device *vfe_dev, + void *arg); }; struct msm_vfe_stats_ops { int (*get_stats_idx)(enum msm_isp_stats_type stats_type); @@ -774,7 +776,7 @@ struct vfe_device { struct msm_isp_statistics *stats; uint64_t msm_isp_last_overflow_ab; uint64_t msm_isp_last_overflow_ib; - uint64_t msm_isp_vfe_clk_rate; + uint32_t msm_isp_vfe_clk_rate; struct msm_isp_ub_info *ub_info; uint32_t isp_sof_debug; uint32_t isp_raw0_debug; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c index 96f9e61578f2..1375d3ce8c65 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c @@ -1054,11 +1054,72 @@ static int msm_vfe40_start_fetch_engine(struct vfe_device *vfe_dev, return 0; } +static int msm_vfe40_start_fetch_engine_multi_pass(struct vfe_device *vfe_dev, + void *arg) +{ + int rc = 0; + uint32_t bufq_handle = 0; + struct msm_isp_buffer *buf = NULL; + struct msm_vfe_fetch_eng_multi_pass_start *fe_cfg = arg; + struct msm_isp_buffer_mapped_info mapped_info; + + if (vfe_dev->fetch_engine_info.is_busy == 1) { + pr_err("%s: fetch engine busy\n", __func__); + return -EINVAL; + } + memset(&mapped_info, 0, sizeof(struct msm_isp_buffer_mapped_info)); + /* There is other option of passing buffer address from user, + * in such case, driver needs to map the buffer and use it + */ + vfe_dev->fetch_engine_info.session_id = fe_cfg->session_id; + vfe_dev->fetch_engine_info.stream_id = fe_cfg->stream_id; + vfe_dev->fetch_engine_info.offline_mode = fe_cfg->offline_mode; + vfe_dev->fetch_engine_info.fd = fe_cfg->fd; + + if (!fe_cfg->offline_mode) { + bufq_handle = vfe_dev->buf_mgr->ops->get_bufq_handle( + vfe_dev->buf_mgr, fe_cfg->session_id, + fe_cfg->stream_id); + vfe_dev->fetch_engine_info.bufq_handle = bufq_handle; + + rc = vfe_dev->buf_mgr->ops->get_buf_by_index( + vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); + if (rc < 0 || !buf) { + pr_err("%s: No fetch buffer rc= %d buf= %p\n", + __func__, rc, buf); + return -EINVAL; + } + mapped_info = buf->mapped_info[0]; + buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED; + } else { + rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr, + &mapped_info, fe_cfg->fd); + if (rc < 0) { + pr_err("%s: can not map buffer\n", __func__); + return -EINVAL; + } + } + vfe_dev->fetch_engine_info.buf_idx = fe_cfg->buf_idx; + vfe_dev->fetch_engine_info.is_busy = 1; + + msm_camera_io_w(mapped_info.paddr + fe_cfg->input_buf_offset, + vfe_dev->vfe_base + 0x228); + + msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x378); + + msm_camera_io_w_mb(0x10000, vfe_dev->vfe_base + 0x4C); + msm_camera_io_w_mb(0x20000, vfe_dev->vfe_base + 0x4C); + + ISP_DBG("%s:VFE%d Fetch Engine ready\n", __func__, vfe_dev->pdev->id); + return 0; +} + static void msm_vfe40_cfg_fetch_engine(struct vfe_device *vfe_dev, struct msm_vfe_pix_cfg *pix_cfg) { uint32_t x_size_word; uint32_t temp = 0; + uint32_t main_unpack_pattern = 0; struct msm_vfe_fetch_engine_cfg *fe_cfg = NULL; if (pix_cfg->input_mux != EXTERNAL_READ) { @@ -1089,10 +1150,14 @@ static void msm_vfe40_cfg_fetch_engine(struct vfe_device *vfe_dev, /* need to update to use formulae to calculate X_SIZE_WORD*/ x_size_word = msm_isp_cal_word_per_line( vfe_dev->axi_data.src_info[VFE_PIX_0].input_format, - fe_cfg->fetch_width); + fe_cfg->buf_width); msm_camera_io_w((x_size_word - 1) << 16, vfe_dev->vfe_base + 0x23C); + x_size_word = msm_isp_cal_word_per_line( + vfe_dev->axi_data.src_info[VFE_PIX_0].input_format, + fe_cfg->fetch_width); + temp = msm_camera_io_r(vfe_dev->vfe_base + 0x1C); temp |= 2 << 16 | pix_cfg->pixel_pattern; msm_camera_io_w(temp, vfe_dev->vfe_base + 0x1C); @@ -1118,7 +1183,19 @@ static void msm_vfe40_cfg_fetch_engine(struct vfe_device *vfe_dev, } /* need to use formulae to calculate MAIN_UNPACK_PATTERN*/ - msm_camera_io_w(0xF6543210, vfe_dev->vfe_base + 0x248); + switch (vfe_dev->axi_data.src_info[VFE_PIX_0].input_format) { + case V4L2_PIX_FMT_P16BGGR10: + case V4L2_PIX_FMT_P16GBRG10: + case V4L2_PIX_FMT_P16GRBG10: + case V4L2_PIX_FMT_P16RGGB10: + main_unpack_pattern = 0xB210; + break; + default: + main_unpack_pattern = 0xF6543210; + break; + } + msm_camera_io_w(main_unpack_pattern, + vfe_dev->vfe_base + 0x248); msm_camera_io_w(0xF, vfe_dev->vfe_base + 0x264); return; @@ -2261,6 +2338,8 @@ struct msm_vfe_hardware_info vfe40_hw_info = { .is_module_cfg_lock_needed = msm_vfe40_is_module_cfg_lock_needed, .ahb_clk_cfg = NULL, + .start_fetch_eng_multi_pass = + msm_vfe40_start_fetch_engine_multi_pass, }, .stats_ops = { .get_stats_idx = msm_vfe40_get_stats_idx, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c index c50c55a69fb5..98e73d48ad15 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c @@ -1077,11 +1077,70 @@ int msm_vfe47_start_fetch_engine(struct vfe_device *vfe_dev, return 0; } +int msm_vfe47_start_fetch_engine_multi_pass(struct vfe_device *vfe_dev, + void *arg) +{ + int rc = 0; + uint32_t bufq_handle = 0; + struct msm_isp_buffer *buf = NULL; + struct msm_vfe_fetch_eng_multi_pass_start *fe_cfg = arg; + struct msm_isp_buffer_mapped_info mapped_info; + + if (vfe_dev->fetch_engine_info.is_busy == 1) { + pr_err("%s: fetch engine busy\n", __func__); + return -EINVAL; + } + + memset(&mapped_info, 0, sizeof(struct msm_isp_buffer_mapped_info)); + + vfe_dev->fetch_engine_info.session_id = fe_cfg->session_id; + vfe_dev->fetch_engine_info.stream_id = fe_cfg->stream_id; + vfe_dev->fetch_engine_info.offline_mode = fe_cfg->offline_mode; + vfe_dev->fetch_engine_info.fd = fe_cfg->fd; + + if (!fe_cfg->offline_mode) { + bufq_handle = vfe_dev->buf_mgr->ops->get_bufq_handle( + vfe_dev->buf_mgr, fe_cfg->session_id, + fe_cfg->stream_id); + vfe_dev->fetch_engine_info.bufq_handle = bufq_handle; + + rc = vfe_dev->buf_mgr->ops->get_buf_by_index( + vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); + if (rc < 0 || !buf) { + pr_err("%s: No fetch buffer rc= %d buf= %pK\n", + __func__, rc, buf); + return -EINVAL; + } + mapped_info = buf->mapped_info[0]; + buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED; + } else { + rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr, + &mapped_info, fe_cfg->fd); + if (rc < 0) { + pr_err("%s: can not map buffer\n", __func__); + return -EINVAL; + } + } + + vfe_dev->fetch_engine_info.buf_idx = fe_cfg->buf_idx; + vfe_dev->fetch_engine_info.is_busy = 1; + + msm_camera_io_w(mapped_info.paddr + fe_cfg->input_buf_offset, + vfe_dev->vfe_base + 0x2F4); + msm_camera_io_w_mb(0x100000, vfe_dev->vfe_base + 0x80); + msm_camera_io_w_mb(0x200000, vfe_dev->vfe_base + 0x80); + + ISP_DBG("%s:VFE%d Fetch Engine ready\n", __func__, vfe_dev->pdev->id); + + return 0; +} + void msm_vfe47_cfg_fetch_engine(struct vfe_device *vfe_dev, struct msm_vfe_pix_cfg *pix_cfg) { uint32_t x_size_word, temp; struct msm_vfe_fetch_engine_cfg *fe_cfg = NULL; + uint32_t main_unpack_pattern = 0; if (pix_cfg->input_mux == EXTERNAL_READ) { fe_cfg = &pix_cfg->fetch_engine_cfg; @@ -1107,10 +1166,13 @@ void msm_vfe47_cfg_fetch_engine(struct vfe_device *vfe_dev, x_size_word = msm_isp_cal_word_per_line( vfe_dev->axi_data.src_info[VFE_PIX_0].input_format, - fe_cfg->fetch_width); + fe_cfg->buf_width); msm_camera_io_w((x_size_word - 1) << 16, vfe_dev->vfe_base + 0x30c); + x_size_word = msm_isp_cal_word_per_line( + vfe_dev->axi_data.src_info[VFE_PIX_0].input_format, + fe_cfg->fetch_width); msm_camera_io_w(x_size_word << 16 | (temp & 0x3FFF) << 2 | VFE47_FETCH_BURST_LEN, vfe_dev->vfe_base + 0x310); @@ -1120,7 +1182,19 @@ void msm_vfe47_cfg_fetch_engine(struct vfe_device *vfe_dev, msm_camera_io_w(temp, vfe_dev->vfe_base + 0x314); /* need to use formulae to calculate MAIN_UNPACK_PATTERN*/ - msm_camera_io_w(0xF6543210, vfe_dev->vfe_base + 0x318); + switch (vfe_dev->axi_data.src_info[VFE_PIX_0].input_format) { + case V4L2_PIX_FMT_P16BGGR10: + case V4L2_PIX_FMT_P16GBRG10: + case V4L2_PIX_FMT_P16GRBG10: + case V4L2_PIX_FMT_P16RGGB10: + main_unpack_pattern = 0xB210; + break; + default: + main_unpack_pattern = 0xF6543210; + break; + } + msm_camera_io_w(main_unpack_pattern, + vfe_dev->vfe_base + 0x318); msm_camera_io_w(0xF, vfe_dev->vfe_base + 0x334); temp = msm_camera_io_r(vfe_dev->vfe_base + 0x50); @@ -2721,6 +2795,8 @@ struct msm_vfe_hardware_info vfe47_hw_info = { .is_module_cfg_lock_needed = msm_vfe47_is_module_cfg_lock_needed, .ahb_clk_cfg = msm_isp47_ahb_clk_cfg, + .start_fetch_eng_multi_pass = + msm_vfe47_start_fetch_engine_multi_pass, }, .stats_ops = { .get_stats_idx = msm_vfe47_get_stats_idx, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.h index 3955196d1deb..6524ac84edf3 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.h @@ -65,6 +65,8 @@ int32_t msm_vfe47_cfg_io_format(struct vfe_device *vfe_dev, enum msm_vfe_axi_stream_src stream_src, uint32_t io_format); int msm_vfe47_start_fetch_engine(struct vfe_device *vfe_dev, void *arg); +int msm_vfe47_start_fetch_engine_multi_pass(struct vfe_device *vfe_dev, + void *arg); void msm_vfe47_cfg_fetch_engine(struct vfe_device *vfe_dev, struct msm_vfe_pix_cfg *pix_cfg); void msm_vfe47_cfg_testgen(struct vfe_device *vfe_dev, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp48.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp48.c index 49520bb44ad8..568125e2d7c2 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp48.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp48.c @@ -309,6 +309,8 @@ struct msm_vfe_hardware_info vfe48_hw_info = { .is_module_cfg_lock_needed = msm_vfe47_is_module_cfg_lock_needed, .ahb_clk_cfg = msm_isp47_ahb_clk_cfg, + .start_fetch_eng_multi_pass = + msm_vfe47_start_fetch_engine_multi_pass, }, .stats_ops = { .get_stats_idx = msm_vfe47_get_stats_idx, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index e8289f05d28f..3b9c3c9d3926 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -1691,6 +1691,76 @@ static struct msm_isp_buffer *msm_isp_get_stream_buffer( return buf; } +int msm_isp_cfg_offline_ping_pong_address(struct vfe_device *vfe_dev, + struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status, + uint32_t buf_idx) +{ + int i, rc = 0; + struct msm_isp_buffer *buf = NULL; + uint32_t pingpong_bit; + uint32_t buffer_size_byte = 0; + int32_t word_per_line = 0; + dma_addr_t paddr; + uint32_t bufq_handle = 0; + int vfe_idx; + + bufq_handle = stream_info->bufq_handle[VFE_BUF_QUEUE_DEFAULT]; + + if (!vfe_dev->is_split) { + rc = vfe_dev->buf_mgr->ops->get_buf_by_index( + vfe_dev->buf_mgr, bufq_handle, buf_idx, &buf); + if (rc < 0 || !buf) { + pr_err("%s: No fetch buffer rc= %d buf= %p\n", + __func__, rc, buf); + return -EINVAL; + } + + if (buf->num_planes != stream_info->num_planes) { + pr_err("%s: Invalid buffer\n", __func__); + vfe_dev->buf_mgr->ops->put_buf(vfe_dev->buf_mgr, + bufq_handle, buf->buf_idx); + return -EINVAL; + } + vfe_idx = msm_isp_get_vfe_idx_for_stream(vfe_dev, stream_info); + pingpong_bit = ((pingpong_status >> + stream_info->wm[vfe_idx][0]) & 0x1); + + for (i = 0; i < stream_info->num_planes; i++) { + word_per_line = msm_isp_cal_word_per_line( + stream_info->output_format, + stream_info->plane_cfg[vfe_idx][i]. + output_stride); + if (word_per_line < 0) { + /* 0 means no prefetch*/ + word_per_line = 0; + buffer_size_byte = 0; + } else { + buffer_size_byte = (word_per_line * 8 * + stream_info->plane_cfg[vfe_idx][i]. + output_scan_lines) - + stream_info-> + plane_cfg[vfe_idx][i].plane_addr_offset; + } + paddr = buf->mapped_info[i].paddr; + + vfe_dev->hw_info->vfe_ops.axi_ops. + update_ping_pong_addr( + vfe_dev->vfe_base, stream_info->wm[vfe_idx][i], + pingpong_bit, paddr + + stream_info-> + plane_cfg[vfe_idx][i].plane_addr_offset, + buffer_size_byte); + stream_info->buf[!pingpong_bit] = buf; + buf->pingpong_bit = !pingpong_bit; + } + buf->state = MSM_ISP_BUFFER_STATE_DEQUEUED; + stream_info->buf[!pingpong_bit] = buf; + buf->pingpong_bit = !pingpong_bit; + } + return rc; + +} + static int msm_isp_cfg_ping_pong_address( struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status) { @@ -1888,6 +1958,11 @@ static int msm_isp_process_done_buf(struct vfe_device *vfe_dev, buf_event.u.buf_done.buf_idx = buf->buf_idx; buf_event.u.buf_done.output_format = stream_info->runtime_output_format; + if (vfe_dev->fetch_engine_info.is_busy && + SRC_TO_INTF(stream_info->stream_src) == VFE_PIX_0) { + vfe_dev->fetch_engine_info.is_busy = 0; + } + if (stream_info->buf_divert && buf_src != MSM_ISP_BUFFER_SRC_SCRATCH) { @@ -2065,7 +2140,8 @@ static void msm_isp_input_enable(struct vfe_device *vfe_dev, continue; /* activate the input since it is deactivated */ axi_data->src_info[i].frame_id = 0; - axi_data->src_info[i].active = 1; + if (axi_data->src_info[i].input_mux != EXTERNAL_READ) + axi_data->src_info[i].active = 1; if (i >= VFE_RAW_0 && sync_frame_id_src) { /* * Incase PIX and RDI streams are part @@ -3534,6 +3610,7 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) unsigned long flags; struct msm_isp_timestamp timestamp; uint32_t frame_id; + int vfe_idx; /*num_stream is uint32 and update_info[] bound by MAX_NUM_STREAM*/ if (update_cmd->num_streams > MAX_NUM_STREAM) @@ -3746,6 +3823,20 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) __func__); break; } + case UPDATE_STREAM_OFFLINE_AXI_CONFIG: { + for (i = 0; i < update_cmd->num_streams; i++) { + update_info = + (struct msm_vfe_axi_stream_cfg_update_info *) + &update_cmd->update_info[i]; + stream_info = msm_isp_get_stream_common_data(vfe_dev, + HANDLE_TO_IDX(update_info->stream_handle)); + vfe_idx = msm_isp_get_vfe_idx_for_stream( + vfe_dev, stream_info); + msm_isp_stream_axi_cfg_update(vfe_dev, stream_info, + update_info); + } + break; + } default: pr_err("%s: Invalid update type %d\n", __func__, update_cmd->update_type); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h index 9c642370b1a1..f9ae5fb74281 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h @@ -157,4 +157,7 @@ static inline struct msm_vfe_axi_stream *msm_isp_vfe_get_stream( index); } +int msm_isp_cfg_offline_ping_pong_address(struct vfe_device *vfe_dev, + struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status, + uint32_t buf_idx); #endif /* __MSM_ISP_AXI_UTIL_H__ */ diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index b0789ce4a71c..72eac5d81627 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -375,6 +375,47 @@ static int msm_isp_start_fetch_engine(struct vfe_device *vfe_dev, start_fetch_eng(vfe_dev, arg); } +static int msm_isp_start_fetch_engine_multi_pass(struct vfe_device *vfe_dev, + void *arg) +{ + struct msm_vfe_fetch_eng_multi_pass_start *fe_cfg = arg; + struct msm_vfe_axi_stream *stream_info = NULL; + int i = 0, rc; + uint32_t wm_reload_mask = 0; + int vfe_idx; + /* + * For Offline VFE, HAL expects same frame id + * for offline output which it requested in do_reprocess. + */ + vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id = + fe_cfg->frame_id; + if (fe_cfg->offline_pass == OFFLINE_SECOND_PASS) { + stream_info = msm_isp_get_stream_common_data(vfe_dev, + HANDLE_TO_IDX(fe_cfg->output_stream_id)); + if (stream_info == NULL) { + pr_err("%s: Error in Offline process\n", __func__); + return -EINVAL; + } + vfe_idx = msm_isp_get_vfe_idx_for_stream(vfe_dev, stream_info); + msm_isp_reset_framedrop(vfe_dev, stream_info); + + rc = msm_isp_cfg_offline_ping_pong_address(vfe_dev, stream_info, + VFE_PING_FLAG, fe_cfg->output_buf_idx); + if (rc < 0) { + pr_err("%s: Fetch engine config failed\n", __func__); + return -EINVAL; + } + for (i = 0; i < stream_info->num_planes; i++) + wm_reload_mask |= (1 << stream_info->wm[vfe_idx][i]); + vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev, + VFE_SRC_MAX); + vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev, + vfe_dev->vfe_base, wm_reload_mask); + } + return vfe_dev->hw_info->vfe_ops.core_ops. + start_fetch_eng_multi_pass(vfe_dev, arg); +} + void msm_isp_fetch_engine_done_notify(struct vfe_device *vfe_dev, struct msm_vfe_fetch_engine_info *fetch_engine_info) { @@ -880,6 +921,13 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, rc = msm_isp_start_fetch_engine(vfe_dev, arg); mutex_unlock(&vfe_dev->core_mutex); break; + + case VIDIOC_MSM_ISP_FETCH_ENG_MULTI_PASS_START: + case VIDIOC_MSM_ISP_MAP_BUF_START_MULTI_PASS_FE: + mutex_lock(&vfe_dev->core_mutex); + rc = msm_isp_start_fetch_engine_multi_pass(vfe_dev, arg); + mutex_unlock(&vfe_dev->core_mutex); + break; case VIDIOC_MSM_ISP_REG_UPDATE_CMD: if (arg) { enum msm_vfe_input_src frame_src = diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c index ab074ffbcdfb..b9018a226f2f 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c @@ -3031,8 +3031,7 @@ STREAM_BUFF_END: uint32_t identity; struct msm_cpp_buff_queue_info_t *buff_queue_info; CPP_DBG("VIDIOC_MSM_CPP_DEQUEUE_STREAM_BUFF_INFO\n"); - if ((ioctl_ptr->len == 0) || - (ioctl_ptr->len > sizeof(uint32_t))) { + if (ioctl_ptr->len != sizeof(uint32_t)) { mutex_unlock(&cpp_dev->mutex); return -EINVAL; } diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c index b1c23823c122..f113bdc5de01 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c +++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c @@ -115,15 +115,16 @@ static int32_t msm_cci_set_clk_param(struct cci_device *cci_dev, enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master; enum i2c_freq_mode_t i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode; - clk_params = &cci_dev->cci_clk_params[i2c_freq_mode]; - if ((i2c_freq_mode >= I2C_MAX_MODES) || (i2c_freq_mode < 0)) { pr_err("%s:%d invalid i2c_freq_mode = %d", __func__, __LINE__, i2c_freq_mode); return -EINVAL; } + if (cci_dev->i2c_freq_mode[master] == i2c_freq_mode) return 0; + + clk_params = &cci_dev->cci_clk_params[i2c_freq_mode]; if (MASTER_0 == master) { msm_camera_io_w_mb(clk_params->hw_thigh << 16 | clk_params->hw_tlow, @@ -1196,6 +1197,13 @@ static uint32_t *msm_cci_get_clk_rates(struct cci_device *cci_dev, struct msm_cci_clk_params_t *clk_params = NULL; enum i2c_freq_mode_t i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode; struct device_node *of_node = cci_dev->pdev->dev.of_node; + + if ((i2c_freq_mode >= I2C_MAX_MODES) || (i2c_freq_mode < 0)) { + pr_err("%s:%d invalid i2c_freq_mode %d\n", + __func__, __LINE__, i2c_freq_mode); + return NULL; + } + clk_params = &cci_dev->cci_clk_params[i2c_freq_mode]; cci_clk_src = clk_params->cci_clk_src; diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 6eee4aa0e574..39cb46a5ce11 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -3456,7 +3456,8 @@ static void mmc_blk_cmdq_err(struct mmc_queue *mq) struct mmc_request *mrq = host->err_mrq; struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx; struct request_queue *q; - int err; + int err, ret; + u32 status = 0; mmc_host_clk_hold(host); host->cmdq_ops->dumpstate(host); @@ -3475,8 +3476,14 @@ static void mmc_blk_cmdq_err(struct mmc_queue *mq) /* RED error - Fatal: requires reset */ if (mrq->cmdq_req->resp_err) { err = mrq->cmdq_req->resp_err; - pr_crit("%s: Response error detected: Device in bad state\n", - mmc_hostname(host)); + if (mmc_host_halt(host) || mmc_host_cq_disable(host)) { + ret = get_card_status(host->card, &status, 0); + if (ret) + pr_err("%s: CMD13 failed with err %d\n", + mmc_hostname(host), ret); + } + pr_err("%s: Response error detected with device status 0x%08x\n", + mmc_hostname(host), status); goto reset; } diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 828d2b85f6e4..6ad91042409e 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1552,6 +1552,12 @@ int mmc_cmdq_halt(struct mmc_host *host, bool halt) { int err = 0; + if (mmc_host_cq_disable(host)) { + pr_debug("%s: %s: CQE is already disabled\n", + mmc_hostname(host), __func__); + return 0; + } + if ((halt && mmc_host_halt(host)) || (!halt && !mmc_host_halt(host))) { pr_debug("%s: %s: CQE is already %s\n", mmc_hostname(host), diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c index 0e0a018f39be..52427815722b 100644 --- a/drivers/mmc/host/cmdq_hci.c +++ b/drivers/mmc/host/cmdq_hci.c @@ -863,8 +863,16 @@ skip_cqterri: * If CQE halt fails then, disable CQE * from processing any further requests */ - if (ret) + if (ret) { cmdq_disable_nosync(mmc, true); + /* + * Enable legacy interrupts as CQE halt has failed. + * This is needed to send legacy commands like status + * cmd as part of error handling work. + */ + if (cq_host->ops->clear_set_irqs) + cq_host->ops->clear_set_irqs(mmc, false); + } /* * CQE detected a reponse error from device diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 0542ba51445f..886229317fea 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -3157,7 +3157,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) do { if (host->mmc->card && mmc_card_cmdq(host->mmc->card) && - !mmc_host_halt(host->mmc)) { + !mmc_host_halt(host->mmc) && !mmc_host_cq_disable(host->mmc)) { pr_debug("*** %s: cmdq intr: 0x%08x\n", mmc_hostname(host->mmc), intmask); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 8676b35914e2..2101147e7d24 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -624,16 +624,16 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) IPADBG("cmd=%x nr=%d\n", cmd, _IOC_NR(cmd)); - if (!ipa3_is_ready()) { - IPAERR("IPA not ready, waiting for init completion\n"); - wait_for_completion(&ipa3_ctx->init_completion_obj); - } - if (_IOC_TYPE(cmd) != IPA_IOC_MAGIC) return -ENOTTY; if (_IOC_NR(cmd) >= IPA_IOCTL_MAX) return -ENOTTY; + if (!ipa3_is_ready()) { + IPAERR("IPA not ready, waiting for init completion\n"); + wait_for_completion(&ipa3_ctx->init_completion_obj); + } + IPA_ACTIVE_CLIENTS_INC_SIMPLE(); switch (cmd) { diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h index d612016b1b79..f0de532f196c 100644 --- a/drivers/power/qcom-charger/fg-core.h +++ b/drivers/power/qcom-charger/fg-core.h @@ -151,6 +151,7 @@ enum fg_sram_param_id { FG_SRAM_CHG_TERM_CURR, FG_SRAM_DELTA_SOC_THR, FG_SRAM_RECHARGE_SOC_THR, + FG_SRAM_RECHARGE_VBATT_THR, FG_SRAM_KI_COEFF_MED_DISCHG, FG_SRAM_KI_COEFF_HI_DISCHG, FG_SRAM_MAX, @@ -198,6 +199,7 @@ struct fg_dt_props { int sys_term_curr_ma; int delta_soc_thr; int recharge_soc_thr; + int recharge_volt_thr_mv; int rsense_sel; int jeita_thresholds[NUM_JEITA_LEVELS]; int esr_timer_charging; diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c index 6ff0e9e45b00..4d2cfc84d455 100644 --- a/drivers/power/qcom-charger/qpnp-fg-gen3.c +++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c @@ -112,6 +112,8 @@ #define EMPTY_VOLT_v2_OFFSET 3 #define VBATT_LOW_v2_WORD 16 #define VBATT_LOW_v2_OFFSET 0 +#define RECHARGE_VBATT_THR_v2_WORD 16 +#define RECHARGE_VBATT_THR_v2_OFFSET 1 #define FLOAT_VOLT_v2_WORD 16 #define FLOAT_VOLT_v2_OFFSET 2 @@ -236,6 +238,9 @@ static struct fg_sram_param pmi8998_v2_sram_params[] = { PARAM(RECHARGE_SOC_THR, RECHARGE_SOC_THR_v2_WORD, RECHARGE_SOC_THR_v2_OFFSET, 1, 256, 100, 0, fg_encode_default, NULL), + PARAM(RECHARGE_VBATT_THR, RECHARGE_VBATT_THR_v2_WORD, + RECHARGE_VBATT_THR_v2_OFFSET, 1, 1000, 15625, -2000, + fg_encode_voltage, NULL), PARAM(ESR_TIMER_DISCHG_MAX, ESR_TIMER_DISCHG_MAX_WORD, ESR_TIMER_DISCHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL), @@ -2395,8 +2400,8 @@ static int fg_hw_init(struct fg_chip *chip) return rc; } - /* This SRAM register is only present in v2.0 */ - if (chip->pmic_rev_id->rev4 == PMI8998_V2P0_REV4 && + /* This SRAM register is only present in v2.0 and above */ + if (chip->pmic_rev_id->rev4 >= PMI8998_V2P0_REV4 && chip->bp.float_volt_uv > 0) { fg_encode(chip->sp, FG_SRAM_FLOAT_VOLT, chip->bp.float_volt_uv / 1000, buf); @@ -2476,6 +2481,23 @@ static int fg_hw_init(struct fg_chip *chip) } } + /* This configuration is available only for pmicobalt v2.0 and above */ + if (chip->pmic_rev_id->rev4 >= PMI8998_V2P0_REV4 && + chip->dt.recharge_volt_thr_mv > 0) { + fg_encode(chip->sp, FG_SRAM_RECHARGE_VBATT_THR, + chip->dt.recharge_volt_thr_mv, buf); + rc = fg_sram_write(chip, + chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_word, + chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_byte, + buf, chip->sp[FG_SRAM_RECHARGE_VBATT_THR].len, + FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing recharge_vbatt_thr, rc=%d\n", + rc); + return rc; + } + } + if (chip->dt.rsense_sel >= SRC_SEL_BATFET && chip->dt.rsense_sel < SRC_SEL_RESERVED) { rc = fg_masked_write(chip, BATT_INFO_IBATT_SENSING_CFG(chip), @@ -2935,6 +2957,7 @@ static int fg_parse_ki_coefficients(struct fg_chip *chip) #define DEFAULT_CUTOFF_VOLT_MV 3200 #define DEFAULT_EMPTY_VOLT_MV 2800 +#define DEFAULT_RECHARGE_VOLT_MV 4250 #define DEFAULT_CHG_TERM_CURR_MA 100 #define DEFAULT_SYS_TERM_CURR_MA -125 #define DEFAULT_DELTA_SOC_THR 1 @@ -3096,6 +3119,12 @@ static int fg_parse_dt(struct fg_chip *chip) else chip->dt.recharge_soc_thr = temp; + rc = of_property_read_u32(node, "qcom,fg-recharge-voltage", &temp); + if (rc < 0) + chip->dt.recharge_volt_thr_mv = DEFAULT_RECHARGE_VOLT_MV; + else + chip->dt.recharge_volt_thr_mv = temp; + rc = of_property_read_u32(node, "qcom,fg-rsense-sel", &temp); if (rc < 0) chip->dt.rsense_sel = SRC_SEL_BATFET_SMB; diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index 738f20d935d6..af20033b621f 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -1984,6 +1984,10 @@ static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt) atomic_set(&gsi->connected, 1); + /* send 0 len pkt to qti to notify state change */ + if (gsi->prot_id == IPA_USB_DIAG) + gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0); + return 0; notify_ep_disable: diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index 5a24a1995af9..5a6d7bc3ff78 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -164,6 +164,7 @@ enum mdss_hw_quirk { MDSS_QUIRK_NEED_SECURE_MAP, MDSS_QUIRK_SRC_SPLIT_ALWAYS, MDSS_QUIRK_MMSS_GDSC_COLLAPSE, + MDSS_QUIRK_MDP_CLK_SET_RATE, MDSS_QUIRK_MAX, }; @@ -289,6 +290,7 @@ struct mdss_data_type { bool en_svs_high; u32 max_mdp_clk_rate; struct mdss_util_intf *mdss_util; + unsigned long mdp_clk_rate; struct platform_device *pdev; struct dss_io_data mdss_io; diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c index bf854a3140b2..d445f95924ef 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_host.c +++ b/drivers/video/fbdev/msm/mdss_dsi_host.c @@ -3128,6 +3128,11 @@ irqreturn_t mdss_dsi_isr(int irq, void *ptr) pr_debug("%s: ndx=%d isr=%x\n", __func__, ctrl->ndx, isr); + if (isr & DSI_INTR_ERROR) { + MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, isr, 0x97); + mdss_dsi_error(ctrl); + } + if (isr & DSI_INTR_BTA_DONE) { MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, isr, 0x96); spin_lock(&ctrl->mdp_lock); @@ -3152,11 +3157,6 @@ irqreturn_t mdss_dsi_isr(int irq, void *ptr) spin_unlock(&ctrl->mdp_lock); } - if (isr & DSI_INTR_ERROR) { - MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, isr, 0x97); - mdss_dsi_error(ctrl); - } - if (isr & DSI_INTR_VIDEO_DONE) { spin_lock(&ctrl->mdp_lock); mdss_dsi_disable_irq_nosync(ctrl, DSI_VIDEO_TERM); diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index 3dfcbfb291ef..58e0d9676736 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -1139,12 +1139,31 @@ static int mdss_mdp_clk_update(u32 clk_idx, u32 enable) { int ret = -ENODEV; struct clk *clk = mdss_mdp_get_clk(clk_idx); + struct mdss_data_type *mdata = mdss_res; if (clk) { pr_debug("clk=%d en=%d\n", clk_idx, enable); if (enable) { if (clk_idx == MDSS_CLK_MDP_VSYNC) clk_set_rate(clk, 19200000); + if (mdss_has_quirk(mdata, MDSS_QUIRK_MDP_CLK_SET_RATE) + && (clk_idx == MDSS_CLK_MDP_CORE)) { + + if (WARN_ON(!mdata->mdp_clk_rate)) { + /* + * rate should have been set in probe + * or during clk scaling; but if this + * is not the case, set max clk rate. + */ + pr_warn("set max mdp clk rate:%u\n", + mdata->max_mdp_clk_rate); + mdss_mdp_set_clk_rate( + mdata->max_mdp_clk_rate, true); + } else { + clk_set_rate(clk, mdata->mdp_clk_rate); + } + } + ret = clk_prepare_enable(clk); } else { clk_disable_unprepare(clk); @@ -1172,7 +1191,7 @@ int mdss_mdp_vsync_clk_enable(int enable, bool locked) return ret; } -void mdss_mdp_set_clk_rate(unsigned long rate) +void mdss_mdp_set_clk_rate(unsigned long rate, bool locked) { struct mdss_data_type *mdata = mdss_res; unsigned long clk_rate; @@ -1182,7 +1201,9 @@ void mdss_mdp_set_clk_rate(unsigned long rate) min_clk_rate = max(rate, mdata->perf_tune.min_mdp_clk); if (clk) { - mutex_lock(&mdp_clk_lock); + + if (!locked) + mutex_lock(&mdp_clk_lock); if (min_clk_rate < mdata->max_mdp_clk_rate) clk_rate = clk_round_rate(clk, min_clk_rate); else @@ -1190,12 +1211,15 @@ void mdss_mdp_set_clk_rate(unsigned long rate) if (IS_ERR_VALUE(clk_rate)) { pr_err("unable to round rate err=%ld\n", clk_rate); } else if (clk_rate != clk_get_rate(clk)) { + + mdata->mdp_clk_rate = clk_rate; if (IS_ERR_VALUE(clk_set_rate(clk, clk_rate))) pr_err("clk_set_rate failed\n"); else pr_debug("mdp clk rate=%lu\n", clk_rate); } - mutex_unlock(&mdp_clk_lock); + if (!locked) + mutex_unlock(&mdp_clk_lock); } else { pr_err("mdp src clk not setup properly\n"); } @@ -1779,7 +1803,7 @@ static int mdss_mdp_irq_clk_setup(struct mdss_data_type *mdata) mdss_mdp_irq_clk_register(mdata, "mnoc_clk", MDSS_CLK_MNOC_AHB); /* Setting the default clock rate to the max supported.*/ - mdss_mdp_set_clk_rate(mdata->max_mdp_clk_rate); + mdss_mdp_set_clk_rate(mdata->max_mdp_clk_rate, false); pr_debug("mdp clk rate=%ld\n", mdss_mdp_get_clk_rate(MDSS_CLK_MDP_CORE, false)); @@ -1816,8 +1840,10 @@ static int mdss_mdp_debug_init(struct platform_device *pdev, mdss_debug_register_dump_range(pdev, dbg_blk, "qcom,regs-dump-mdp", "qcom,regs-dump-names-mdp", "qcom,regs-dump-xin-id-mdp"); - mdss_debug_register_io("vbif", &mdata->vbif_io, NULL); - mdss_debug_register_io("vbif_nrt", &mdata->vbif_nrt_io, NULL); + if (mdata->vbif_io.base) + mdss_debug_register_io("vbif", &mdata->vbif_io, NULL); + if (mdata->vbif_nrt_io.base) + mdss_debug_register_io("vbif_nrt", &mdata->vbif_nrt_io, NULL); return 0; } @@ -2020,6 +2046,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata) mdss_set_quirk(mdata, MDSS_QUIRK_DSC_RIGHT_ONLY_PU); mdss_set_quirk(mdata, MDSS_QUIRK_DSC_2SLICE_PU_THRPUT); mdss_set_quirk(mdata, MDSS_QUIRK_MMSS_GDSC_COLLAPSE); + mdss_set_quirk(mdata, MDSS_QUIRK_MDP_CLK_SET_RATE); mdata->has_wb_ubwc = true; set_bit(MDSS_CAPS_10_BIT_SUPPORTED, mdata->mdss_caps_map); set_bit(MDSS_CAPS_AVR_SUPPORTED, mdata->mdss_caps_map); diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index 623c588ae456..c5cec4cd6f93 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -1590,7 +1590,7 @@ u32 mdss_mdp_get_irq_mask(u32 intr_type, u32 intf_num); void mdss_mdp_footswitch_ctrl_splash(int on); void mdss_mdp_batfet_ctrl(struct mdss_data_type *mdata, int enable); -void mdss_mdp_set_clk_rate(unsigned long min_clk_rate); +void mdss_mdp_set_clk_rate(unsigned long min_clk_rate, bool locked); unsigned long mdss_mdp_get_clk_rate(u32 clk_idx, bool locked); int mdss_mdp_vsync_clk_enable(int enable, bool locked); void mdss_mdp_clk_ctrl(int enable); diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index 169095f64a0f..1c013ae723aa 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -2375,7 +2375,7 @@ static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl, */ if (update_clk) { ATRACE_INT("mdp_clk", clk_rate); - mdss_mdp_set_clk_rate(clk_rate); + mdss_mdp_set_clk_rate(clk_rate, false); pr_debug("update clk rate = %d HZ\n", clk_rate); } @@ -5495,8 +5495,13 @@ int mdss_mdp_ctl_update_fps(struct mdss_mdp_ctl *ctl) (pinfo->dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP) || (pinfo->dfps_update == DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP) || + (pinfo->dfps_update == + DFPS_IMMEDIATE_MULTI_MODE_HFP_CALC_CLK) || pinfo->dfps_update == DFPS_IMMEDIATE_CLK_UPDATE_MODE) { - new_fps = mdss_panel_get_framerate(pinfo); + if (pinfo->type == DTV_PANEL) + new_fps = pinfo->lcdc.frame_rate; + else + new_fps = mdss_panel_get_framerate(pinfo); } else { new_fps = pinfo->new_fps; } diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c index fabdc5cd3e42..5d5515a91572 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c @@ -1424,7 +1424,9 @@ static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, int new_fps) pdata->panel_info.dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP || pdata->panel_info.dfps_update - == DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP) { + == DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP || + pdata->panel_info.dfps_update + == DFPS_IMMEDIATE_MULTI_MODE_HFP_CALC_CLK) { unsigned long flags; if (!ctx->timegen_en) { pr_err("TG is OFF. DFPS mode invalid\n"); diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 0203c0e69e3f..154b9d86e67c 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -3064,16 +3064,23 @@ static void cache_initial_timings(struct mdss_panel_data *pdata) * This value will change dynamically once the * actual dfps update happen in hw. */ - pdata->panel_info.current_fps = - mdss_panel_get_framerate(&pdata->panel_info); - + if (pdata->panel_info.type == DTV_PANEL) + pdata->panel_info.current_fps = + pdata->panel_info.lcdc.frame_rate; + else + pdata->panel_info.current_fps = + mdss_panel_get_framerate(&pdata->panel_info); /* * Keep the initial fps and porch values for this panel before * any dfps update happen, this is to prevent losing precision * in further calculations. */ - pdata->panel_info.default_fps = - mdss_panel_get_framerate(&pdata->panel_info); + if (pdata->panel_info.type == DTV_PANEL) + pdata->panel_info.default_fps = + pdata->panel_info.lcdc.frame_rate; + else + pdata->panel_info.default_fps = + mdss_panel_get_framerate(&pdata->panel_info); if (pdata->panel_info.dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP) { @@ -3085,7 +3092,9 @@ static void cache_initial_timings(struct mdss_panel_data *pdata) } else if (pdata->panel_info.dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP || pdata->panel_info.dfps_update == - DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP) { + DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP || + pdata->panel_info.dfps_update == + DFPS_IMMEDIATE_MULTI_MODE_HFP_CALC_CLK) { pdata->panel_info.saved_total = mdss_panel_get_htotal(&pdata->panel_info, true); pdata->panel_info.saved_fporch = @@ -3154,8 +3163,25 @@ static void dfps_update_panel_params(struct mdss_panel_data *pdata, pdata->panel_info.lcdc.h_pulse_width = data->hpw; pdata->panel_info.clk_rate = data->clk_rate; + if (pdata->panel_info.type == DTV_PANEL) + pdata->panel_info.clk_rate *= 1000; + + dfps_update_fps(&pdata->panel_info, new_fps); + } else if (pdata->panel_info.dfps_update == + DFPS_IMMEDIATE_MULTI_MODE_HFP_CALC_CLK) { + + pr_debug("hfp=%d, hbp=%d, hpw=%d, clk=%d, fps=%d\n", + data->hfp, data->hbp, data->hpw, + data->clk_rate, data->fps); + + pdata->panel_info.lcdc.h_front_porch = data->hfp; + pdata->panel_info.lcdc.h_back_porch = data->hbp; + pdata->panel_info.lcdc.h_pulse_width = data->hpw; + + pdata->panel_info.clk_rate = data->clk_rate; dfps_update_fps(&pdata->panel_info, new_fps); + mdss_panel_update_clk_rate(&pdata->panel_info, new_fps); } else { dfps_update_fps(&pdata->panel_info, new_fps); mdss_panel_update_clk_rate(&pdata->panel_info, new_fps); @@ -3230,7 +3256,9 @@ static ssize_t dynamic_fps_sysfs_wta_dfps(struct device *dev, } if (pdata->panel_info.dfps_update == - DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP) { + DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP || + pdata->panel_info.dfps_update == + DFPS_IMMEDIATE_MULTI_MODE_HFP_CALC_CLK) { if (sscanf(buf, "%u %u %u %u %u", &data.hfp, &data.hbp, &data.hpw, &data.clk_rate, &data.fps) != 5) { @@ -3245,7 +3273,10 @@ static ssize_t dynamic_fps_sysfs_wta_dfps(struct device *dev, } } - panel_fps = mdss_panel_get_framerate(&pdata->panel_info); + if (pdata->panel_info.type == DTV_PANEL) + panel_fps = pdata->panel_info.lcdc.frame_rate; + else + panel_fps = mdss_panel_get_framerate(&pdata->panel_info); if (data.fps == panel_fps) { pr_debug("%s: FPS is already %d\n", @@ -3308,7 +3339,7 @@ static ssize_t mdss_mdp_lineptr_show_event(struct device *dev, if (!mdp5_data->ctl || (!mdp5_data->ctl->panel_data->panel_info.cont_splash_enabled && !mdss_mdp_ctl_is_power_on(mdp5_data->ctl))) - return -EAGAIN; + return -EPERM; lineptr_ticks = ktime_to_ns(mdp5_data->lineptr_time); @@ -3329,7 +3360,7 @@ static ssize_t mdss_mdp_lineptr_show_value(struct device *dev, if (!mdp5_data->ctl || (!mdp5_data->ctl->panel_data->panel_info.cont_splash_enabled && !mdss_mdp_ctl_is_power_on(mdp5_data->ctl))) - return -EAGAIN; + return -EPERM; lineptr_val = mfd->panel_info->te.wr_ptr_irq; diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index 25ae326ebbc3..16bb48e22bee 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -540,7 +540,10 @@ struct dynamic_fps_data { * @DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP: update fps using vertical timings * @DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP: update fps using horizontal timings * @DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP: update fps using both horizontal - * timings and clock. + * timings and clock. + * @DFPS_IMMEDIATE_MULTI_MODE_HFP_CALC_CLK: update fps using both + * horizontal timings, clock need to be caculate base on new clock and + * porches. * @DFPS_MODE_MAX: defines maximum limit of supported modes. */ enum dynamic_fps_update { @@ -549,6 +552,7 @@ enum dynamic_fps_update { DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP, DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP, DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP, + DFPS_IMMEDIATE_MULTI_MODE_HFP_CALC_CLK, DFPS_MODE_MAX }; @@ -978,7 +982,9 @@ static inline u32 mdss_panel_get_framerate(struct mdss_panel_info *panel_info) break; case DTV_PANEL: if (panel_info->dynamic_fps) { - frame_rate = panel_info->lcdc.frame_rate; + frame_rate = panel_info->lcdc.frame_rate / 1000; + if (panel_info->lcdc.frame_rate % 1000) + frame_rate += 1; break; } default: diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 83e9c6e23f2f..aed90a4902c7 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -788,7 +788,8 @@ int of_clk_get_parent_count(struct device_node *np); int of_clk_parent_fill(struct device_node *np, const char **parents, unsigned int size); const char *of_clk_get_parent_name(struct device_node *np, int index); - +int of_clk_detect_critical(struct device_node *np, int index, + unsigned long *flags); void of_clk_init(const struct of_device_id *matches); #else /* !CONFIG_OF */ @@ -826,6 +827,13 @@ static inline const char *of_clk_get_parent_name(struct device_node *np, { return NULL; } + +static inline int of_clk_detect_critical(struct device_node *np, int index, + unsigned long *flags) +{ + return 0; +} + #define of_clk_init(matches) \ { while (0); } #endif /* CONFIG_OF */ diff --git a/include/uapi/media/msmb_isp.h b/include/uapi/media/msmb_isp.h index cdb85170919a..e4d41d4072c5 100644 --- a/include/uapi/media/msmb_isp.h +++ b/include/uapi/media/msmb_isp.h @@ -261,6 +261,26 @@ struct msm_vfe_fetch_eng_start { uint32_t frame_id; }; +enum msm_vfe_fetch_eng_pass { + OFFLINE_FIRST_PASS, + OFFLINE_SECOND_PASS, + OFFLINE_MAX_PASS, +}; + +struct msm_vfe_fetch_eng_multi_pass_start { + uint32_t session_id; + uint32_t stream_id; + uint32_t buf_idx; + uint8_t offline_mode; + uint32_t fd; + uint32_t buf_addr; + uint32_t frame_id; + uint32_t output_buf_idx; + uint32_t input_buf_offset; + enum msm_vfe_fetch_eng_pass offline_pass; + uint32_t output_stream_id; +}; + struct msm_vfe_axi_plane_cfg { uint32_t output_width; /*Include padding*/ uint32_t output_height; @@ -328,6 +348,7 @@ enum msm_vfe_axi_stream_update_type { UPDATE_STREAM_REMOVE_BUFQ, UPDATE_STREAM_SW_FRAME_DROP, UPDATE_STREAM_REQUEST_FRAMES_VER2, + UPDATE_STREAM_OFFLINE_AXI_CONFIG, }; #define UPDATE_STREAM_REQUEST_FRAMES_VER2 UPDATE_STREAM_REQUEST_FRAMES_VER2 @@ -853,6 +874,8 @@ enum msm_isp_ioctl_cmd_code { MSM_ISP_SET_DUAL_HW_MASTER_SLAVE, MSM_ISP_MAP_BUF_START_FE, MSM_ISP_UNMAP_BUF, + MSM_ISP_FETCH_ENG_MULTI_PASS_START, + MSM_ISP_MAP_BUF_START_MULTI_PASS_FE, }; #define VIDIOC_MSM_VFE_REG_CFG \ @@ -958,4 +981,11 @@ enum msm_isp_ioctl_cmd_code { #define VIDIOC_MSM_ISP_AHB_CLK_CFG \ _IOWR('V', BASE_VIDIOC_PRIVATE+25, struct msm_isp_ahb_clk_cfg) +#define VIDIOC_MSM_ISP_FETCH_ENG_MULTI_PASS_START \ + _IOWR('V', MSM_ISP_FETCH_ENG_MULTI_PASS_START, \ + struct msm_vfe_fetch_eng_multi_pass_start) + +#define VIDIOC_MSM_ISP_MAP_BUF_START_MULTI_PASS_FE \ + _IOWR('V', MSM_ISP_MAP_BUF_START_MULTI_PASS_FE, \ + struct msm_vfe_fetch_eng_multi_pass_start) #endif /* __MSMB_ISP__ */ diff --git a/kernel/sched/hmp.c b/kernel/sched/hmp.c index a9ccb63c8e23..5ff7a11d043f 100644 --- a/kernel/sched/hmp.c +++ b/kernel/sched/hmp.c @@ -1771,20 +1771,20 @@ static int send_notification(struct rq *rq, int check_pred, int check_groups) if (freq_required < cur_freq + sysctl_sched_pred_alert_freq) return 0; } else { - read_lock(&related_thread_group_lock); + read_lock_irqsave(&related_thread_group_lock, flags); /* * Protect from concurrent update of rq->prev_runnable_sum and * group cpu load */ - raw_spin_lock_irqsave(&rq->lock, flags); + raw_spin_lock(&rq->lock); if (check_groups) _group_load_in_cpu(cpu_of(rq), &group_load, NULL); new_load = rq->prev_runnable_sum + group_load; new_load = freq_policy_load(rq, new_load); - raw_spin_unlock_irqrestore(&rq->lock, flags); - read_unlock(&related_thread_group_lock); + raw_spin_unlock(&rq->lock); + read_unlock_irqrestore(&related_thread_group_lock, flags); cur_freq = load_to_freq(rq, rq->old_busy_time); freq_required = load_to_freq(rq, new_load); @@ -3206,14 +3206,16 @@ void sched_get_cpus_busy(struct sched_load *busy, if (unlikely(cpus == 0)) return; + local_irq_save(flags); + + read_lock(&related_thread_group_lock); + /* * This function could be called in timer context, and the * current task may have been executing for a long time. Ensure * that the window stats are current by doing an update. */ - read_lock(&related_thread_group_lock); - local_irq_save(flags); for_each_cpu(cpu, query_cpus) raw_spin_lock(&cpu_rq(cpu)->lock); @@ -3313,10 +3315,11 @@ skip_early: for_each_cpu(cpu, query_cpus) raw_spin_unlock(&(cpu_rq(cpu))->lock); - local_irq_restore(flags); read_unlock(&related_thread_group_lock); + local_irq_restore(flags); + i = 0; for_each_cpu(cpu, query_cpus) { rq = cpu_rq(cpu); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 7a5fa0c98377..2b67ae1c53e4 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -926,16 +926,6 @@ static void netlink_skb_set_owner_r(struct sk_buff *skb, struct sock *sk) static void netlink_sock_destruct(struct sock *sk) { - struct netlink_sock *nlk = nlk_sk(sk); - - if (nlk->cb_running) { - if (nlk->cb.done) - nlk->cb.done(&nlk->cb); - - module_put(nlk->cb.module); - kfree_skb(nlk->cb.skb); - } - skb_queue_purge(&sk->sk_receive_queue); #ifdef CONFIG_NETLINK_MMAP if (1) { @@ -1070,8 +1060,9 @@ static struct sock *netlink_lookup(struct net *net, int protocol, u32 portid) rcu_read_lock(); sk = __netlink_lookup(table, portid, net); - if (sk) - sock_hold(sk); + if (sk && !atomic_inc_not_zero(&sk->sk_refcnt)) + sk = NULL; + rcu_read_unlock(); return sk; @@ -1198,6 +1189,7 @@ static int __netlink_create(struct net *net, struct socket *sock, mutex_init(&nlk->pg_vec_lock); #endif + sock_set_flag(sk, SOCK_RCU_FREE); sk->sk_destruct = netlink_sock_destruct; sk->sk_protocol = protocol; return 0; @@ -1262,13 +1254,6 @@ out_module: goto out; } -static void deferred_put_nlk_sk(struct rcu_head *head) -{ - struct netlink_sock *nlk = container_of(head, struct netlink_sock, rcu); - - sock_put(&nlk->sk); -} - static int netlink_release(struct socket *sock) { struct sock *sk = sock->sk; @@ -1341,7 +1326,19 @@ static int netlink_release(struct socket *sock) local_bh_disable(); sock_prot_inuse_add(sock_net(sk), &netlink_proto, -1); local_bh_enable(); - call_rcu(&nlk->rcu, deferred_put_nlk_sk); + if (nlk->cb_running) { + mutex_lock(nlk->cb_mutex); + if (nlk->cb_running) { + if (nlk->cb.done) + nlk->cb.done(&nlk->cb); + + module_put(nlk->cb.module); + kfree_skb(nlk->cb.skb); + nlk->cb_running = false; + } + mutex_unlock(nlk->cb_mutex); + } + sock_put(sk); return 0; } diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h index 14437d9b1965..6acee01a419f 100644 --- a/net/netlink/af_netlink.h +++ b/net/netlink/af_netlink.h @@ -52,7 +52,6 @@ struct netlink_sock { #endif /* CONFIG_NETLINK_MMAP */ struct rhash_head node; - struct rcu_head rcu; }; static inline struct netlink_sock *nlk_sk(struct sock *sk) |
