Merge "drm/msm/dsi-staging: add support for configuring display topology" into msm-4.9
diff --git a/Documentation/devicetree/bindings/display/msm/sde.txt b/Documentation/devicetree/bindings/display/msm/sde.txt
index bc226a7..a3ef34c 100644
--- a/Documentation/devicetree/bindings/display/msm/sde.txt
+++ b/Documentation/devicetree/bindings/display/msm/sde.txt
@@ -128,6 +128,8 @@
feature is available or not.
- qcom,sde-has-dim-layer: Boolean property to indicate if mixer has dim layer
feature is available or not.
+- qcom,sde-has-idle-pc: Boolean property to indicate if target has idle
+ power collapse feature available or not.
- qcom,sde-has-mixer-gc: Boolean property to indicate if mixer has gamma correction
feature available or not.
- qcom,sde-has-cdp: Boolean property to indicate if cdp feature is
@@ -420,6 +422,7 @@
qcom,sde-csc-type = "csc-10bit";
qcom,sde-highest-bank-bit = <15>;
qcom,sde-has-mixer-gc;
+ qcom,sde-has-idle-pc;
qcom,sde-sspp-max-rects = <1 1 1 1
1 1 1 1
1 1
diff --git a/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt
index fe0e0e4..ffba081 100644
--- a/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt
@@ -35,7 +35,7 @@
- qcom,mdss-dsi-panel-destination: A string that specifies the destination display for the panel.
"display_1" = DISPLAY_1
"display_2" = DISPLAY_2
-- qcom,mdss-dsi-panel-timings: An array of length 12 that specifies the PHY
+- qcom,mdss-dsi-panel-phy-timings: An array of length 12 that specifies the PHY
timing settings for the panel.
- qcom,mdss-dsi-panel-timings-8996: An array of length 40 char that specifies the 8996 PHY lane
timing settings for the panel.
diff --git a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp.dts b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp.dts
index d5646bf..6569219 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp.dts
@@ -21,3 +21,26 @@
compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp";
qcom,board-id = <1 1>;
};
+
+&dsi_dual_nt35597_truly_video_display {
+ /delete-property/ qcom,dsi-display-active;
+};
+
+&mdss_mdp {
+ connectors = <&sde_wb &dsi_sharp_4k_dsc_video_display>;
+};
+
+&dsi_sharp_4k_dsc_video {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-panel-mode-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_sharp_4k_dsc_video_display {
+ qcom,dsi-display-active;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp.dts
index d641276..2e893de 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp.dts
@@ -21,3 +21,26 @@
compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp";
qcom,board-id = <8 1>;
};
+
+&dsi_dual_nt35597_truly_video_display {
+ /delete-property/ qcom,dsi-display-active;
+};
+
+&mdss_mdp {
+ connectors = <&sde_wb &dsi_sharp_4k_dsc_video_display>;
+};
+
+&dsi_sharp_4k_dsc_video {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-panel-mode-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_sharp_4k_dsc_video_display {
+ qcom,dsi-display-active;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi
index c0189a4..922e990 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi
@@ -118,10 +118,12 @@
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_rear_ldo>;
- qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
- qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
- qcom,cam-vreg-op-mode = <0 80000 105000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000 0>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000 0>;
+ qcom,cam-vreg-op-mode = <0 80000 105000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_active
@@ -157,10 +159,12 @@
cam_vdig-supply = <&camera_ldo>;
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
- qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
- qcom,cam-vreg-min-voltage = <1050000 0 3312000>;
- qcom,cam-vreg-max-voltage = <1050000 0 3600000>;
- qcom,cam-vreg-op-mode = <105000 0 80000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <1050000 0 3312000 0>;
+ qcom,cam-vreg-max-voltage = <1050000 0 3600000 0>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk2_active
@@ -193,10 +197,12 @@
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_ldo>;
- qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
- qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
- qcom,cam-vreg-op-mode = <0 80000 105000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000 0>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000 0>;
+ qcom,cam-vreg-op-mode = <0 80000 105000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk1_active
@@ -240,10 +246,12 @@
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_rear_ldo>;
- qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
- qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
- qcom,cam-vreg-op-mode = <0 80000 105000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000 0>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000 0>;
+ qcom,cam-vreg-op-mode = <0 80000 105000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_active
@@ -280,10 +288,12 @@
cam_vdig-supply = <&camera_ldo>;
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
- qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
- qcom,cam-vreg-min-voltage = <1050000 0 3312000>;
- qcom,cam-vreg-max-voltage = <1050000 0 3600000>;
- qcom,cam-vreg-op-mode = <105000 0 80000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <1050000 0 3312000 0>;
+ qcom,cam-vreg-max-voltage = <1050000 0 3600000 0>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk2_active
@@ -322,10 +332,12 @@
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_ldo>;
- qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
- qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
- qcom,cam-vreg-op-mode = <0 80000 105000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000 0>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000 0>;
+ qcom,cam-vreg-op-mode = <0 80000 105000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk1_active
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
index c0189a4..922e990 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
@@ -118,10 +118,12 @@
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_rear_ldo>;
- qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
- qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
- qcom,cam-vreg-op-mode = <0 80000 105000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000 0>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000 0>;
+ qcom,cam-vreg-op-mode = <0 80000 105000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_active
@@ -157,10 +159,12 @@
cam_vdig-supply = <&camera_ldo>;
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
- qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
- qcom,cam-vreg-min-voltage = <1050000 0 3312000>;
- qcom,cam-vreg-max-voltage = <1050000 0 3600000>;
- qcom,cam-vreg-op-mode = <105000 0 80000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <1050000 0 3312000 0>;
+ qcom,cam-vreg-max-voltage = <1050000 0 3600000 0>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk2_active
@@ -193,10 +197,12 @@
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_ldo>;
- qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
- qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
- qcom,cam-vreg-op-mode = <0 80000 105000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000 0>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000 0>;
+ qcom,cam-vreg-op-mode = <0 80000 105000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk1_active
@@ -240,10 +246,12 @@
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_rear_ldo>;
- qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
- qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
- qcom,cam-vreg-op-mode = <0 80000 105000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000 0>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000 0>;
+ qcom,cam-vreg-op-mode = <0 80000 105000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_active
@@ -280,10 +288,12 @@
cam_vdig-supply = <&camera_ldo>;
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
- qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
- qcom,cam-vreg-min-voltage = <1050000 0 3312000>;
- qcom,cam-vreg-max-voltage = <1050000 0 3600000>;
- qcom,cam-vreg-op-mode = <105000 0 80000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <1050000 0 3312000 0>;
+ qcom,cam-vreg-max-voltage = <1050000 0 3600000 0>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk2_active
@@ -322,10 +332,12 @@
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_ldo>;
- qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
- qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
- qcom,cam-vreg-op-mode = <0 80000 105000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000 0>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000 0>;
+ qcom,cam-vreg-op-mode = <0 80000 105000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk1_active
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
index cd9c8a8..3b9c26f 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
@@ -71,7 +71,7 @@
<&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>,
<&clock_camcc CAM_CC_CSIPHY1_CLK>,
<&clock_camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>,
- <&clock_camcc CAM_CC_CSI0PHYTIMER_CLK>,
+ <&clock_camcc CAM_CC_CSI1PHYTIMER_CLK>,
<&clock_camcc CAM_CC_IFE_1_CSID_CLK>,
<&clock_camcc CAM_CC_IFE_1_CSID_CLK_SRC>;
clock-names = "camnoc_axi_clk",
@@ -225,4 +225,108 @@
status = "ok";
};
};
+
+ qcom,cam_smmu {
+ compatible = "qcom,msm-cam-smmu";
+ status = "ok";
+
+ msm_cam_smmu_ife {
+ compatible = "qcom,msm-cam-smmu-cb";
+ iommus = <&apps_smmu 0x808>,
+ <&apps_smmu 0x810>,
+ <&apps_smmu 0x818>,
+ <&apps_smmu 0xc08>,
+ <&apps_smmu 0xc10>,
+ <&apps_smmu 0xc18>;
+ label = "ife";
+ ife_iova_mem_map: iova-mem-map {
+ /* IO region is approximately 3.4 GB */
+ iova-mem-region-io {
+ iova-region-name = "io";
+ iova-region-start = <0x7400000>;
+ iova-region-len = <0xd8c00000>;
+ iova-region-id = <0x3>;
+ status = "ok";
+ };
+ };
+ };
+
+ msm_cam_icp_fw {
+ compatible = "qcom,msm-cam-smmu-fw-dev";
+ label="icp";
+ memory-region = <&pil_camera_mem>;
+ };
+
+ msm_cam_smmu_icp {
+ compatible = "qcom,msm-cam-smmu-cb";
+ iommus = <&apps_smmu 0x1078>,
+ <&apps_smmu 0x1020>,
+ <&apps_smmu 0x1028>,
+ <&apps_smmu 0x1040>,
+ <&apps_smmu 0x1048>,
+ <&apps_smmu 0x1030>,
+ <&apps_smmu 0x1050>;
+ label = "icp";
+ icp_iova_mem_map: iova-mem-map {
+ iova-mem-region-firmware {
+ /* Firmware region is 5MB */
+ iova-region-name = "firmware";
+ iova-region-start = <0x0>;
+ iova-region-len = <0x500000>;
+ iova-region-id = <0x0>;
+ status = "ok";
+ };
+
+ iova-mem-region-shared {
+ /* Shared region is 100MB long */
+ iova-region-name = "shared";
+ iova-region-start = <0x7400000>;
+ iova-region-len = <0x6400000>;
+ iova-region-id = <0x1>;
+ status = "ok";
+ };
+
+ iova-mem-region-io {
+ /* IO region is approximately 3.3 GB */
+ iova-region-name = "io";
+ iova-region-start = <0xd800000>;
+ iova-region-len = <0xd2800000>;
+ iova-region-id = <0x3>;
+ status = "ok";
+ };
+ };
+ };
+
+ msm_cam_smmu_cpas_cdm {
+ compatible = "qcom,msm-cam-smmu-cb";
+ iommus = <&apps_smmu 0x1000>;
+ label = "cpas-cdm0";
+ cpas_cdm_iova_mem_map: iova-mem-map {
+ iova-mem-region-io {
+ /* IO region is approximately 3.4 GB */
+ iova-region-name = "io";
+ iova-region-start = <0x7400000>;
+ iova-region-len = <0xd8c00000>;
+ iova-region-id = <0x3>;
+ status = "ok";
+ };
+ };
+ };
+
+ msm_cam_smmu_secure {
+ compatible = "qcom,msm-cam-smmu-cb";
+ iommus = <&apps_smmu 0x1001>;
+ label = "cam-secure";
+ cam_secure_iova_mem_map: iova-mem-map {
+ /* Secure IO region is approximately 3.4 GB */
+ iova-mem-region-io {
+ iova-region-name = "io";
+ iova-region-start = <0x7400000>;
+ iova-region-len = <0xd8c00000>;
+ iova-region-id = <0x3>;
+ status = "ok";
+ };
+ };
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi b/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
index 5e21756..0ada391 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
@@ -77,13 +77,16 @@
#cooling-cells = <2>;
clocks = <&clock_gfx GPU_CC_GX_GFX3D_CLK>,
- <&clock_gcc GCC_GPU_CFG_AHB_CLK>,
<&clock_gpucc GPU_CC_CXO_CLK>,
<&clock_gcc GCC_DDRSS_GPU_AXI_CLK>,
- <&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>;
+ <&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>,
+ <&clock_gpucc GPU_CC_CX_GMU_CLK>,
+ <&clock_gpucc GPU_CC_AHB_CLK>,
+ <&clock_gpucc GPU_CC_GX_CXO_CLK>;
- clock-names = "core_clk", "iface_clk", "rbbmtimer_clk",
- "mem_clk", "mem_iface_clk";
+ clock-names = "core_clk", "rbbmtimer_clk", "mem_clk",
+ "mem_iface_clk", "gmu_clk", "ahb_clk",
+ "cxo_clk";
qcom,isense-clk-on-level = <1>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
index 7f24c8b..efd8f45 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
@@ -116,6 +116,7 @@
pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
qcom,platform-te-gpio = <&tlmm 10 0>;
qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
qcom,dsi-panel = <&dsi_sharp_4k_dsc_video>;
vddio-supply = <&pm8998_l14>;
@@ -139,6 +140,7 @@
pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
qcom,platform-te-gpio = <&tlmm 10 0>;
qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
qcom,dsi-panel = <&dsi_sharp_4k_dsc_cmd>;
vddio-supply = <&pm8998_l14>;
@@ -162,6 +164,7 @@
pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
qcom,platform-te-gpio = <&tlmm 10 0>;
qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
qcom,dsi-panel = <&dsi_sharp_1080_cmd>;
vddio-supply = <&pm8998_l14>;
@@ -185,6 +188,7 @@
pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
qcom,platform-te-gpio = <&tlmm 10 0>;
qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
qcom,dsi-panel = <&dsi_dual_sharp_1080_120hz_cmd>;
vddio-supply = <&pm8998_l14>;
@@ -231,6 +235,7 @@
pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
qcom,platform-te-gpio = <&tlmm 10 0>;
qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
qcom,dsi-panel = <&dsi_dual_nt35597_truly_cmd>;
vddio-supply = <&pm8998_l14>;
@@ -254,6 +259,7 @@
pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
qcom,platform-te-gpio = <&tlmm 10 0>;
qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
qcom,dsi-panel = <&dsi_nt35597_truly_dsc_cmd>;
vddio-supply = <&pm8998_l14>;
@@ -277,6 +283,7 @@
pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
qcom,platform-te-gpio = <&tlmm 10 0>;
qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
qcom,dsi-panel = <&dsi_nt35597_truly_dsc_video>;
vddio-supply = <&pm8998_l14>;
@@ -296,43 +303,43 @@
};
&dsi_dual_nt35597_truly_video {
- qcom,mdss-dsi-panel-timings = [00 1c 07 07 23 21 07 07 05 03 04];
+ qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07 07 05 03 04 00];
qcom,mdss-dsi-t-clk-post = <0x0D>;
qcom,mdss-dsi-t-clk-pre = <0x2D>;
};
&dsi_dual_nt35597_truly_cmd {
- qcom,mdss-dsi-panel-timings = [00 1c 07 07 23 21 07 07 05 03 04];
+ qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07 07 05 03 04 00];
qcom,mdss-dsi-t-clk-post = <0x0D>;
qcom,mdss-dsi-t-clk-pre = <0x2D>;
};
&dsi_nt35597_truly_dsc_cmd {
- qcom,mdss-dsi-panel-timings = [00 15 05 05 20 1f 05 05 03 03 04];
+ qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05 05 03 03 04 00];
qcom,mdss-dsi-t-clk-post = <0x0b>;
qcom,mdss-dsi-t-clk-pre = <0x23>;
};
&dsi_nt35597_truly_dsc_video {
- qcom,mdss-dsi-panel-timings = [00 15 05 05 20 1f 05 05 03 03 04];
+ qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05 05 03 03 04 00];
qcom,mdss-dsi-t-clk-post = <0x0b>;
qcom,mdss-dsi-t-clk-pre = <0x23>;
};
&dsi_sharp_4k_dsc_video {
- qcom,mdss-dsi-panel-timings = [00 12 04 04 1e 1e 04 04 02 03 04];
- qcom,mdss-dsi-t-clk-post = <0x0a>;
- qcom,mdss-dsi-t-clk-pre = <0x1e>;
+ qcom,mdss-dsi-panel-phy-timings = [00 18 06 06 21 20 06 06 04 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x0c>;
+ qcom,mdss-dsi-t-clk-pre = <0x27>;
};
&dsi_sharp_4k_dsc_cmd {
- qcom,mdss-dsi-panel-timings = [00 12 04 04 1e 1e 04 04 02 03 04];
- qcom,mdss-dsi-t-clk-post = <0x0a>;
- qcom,mdss-dsi-t-clk-pre = <0x1e>;
+ qcom,mdss-dsi-panel-phy-timings = [00 18 06 06 21 20 06 06 04 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x0c>;
+ qcom,mdss-dsi-t-clk-pre = <0x27>;
};
&dsi_dual_sharp_1080_120hz_cmd {
- qcom,mdss-dsi-panel-timings = [00 24 09 09 26 24 09 09 06 03 04];
+ qcom,mdss-dsi-panel-phy-timings = [00 24 09 09 26 24 09 09 06 03 04 00];
qcom,mdss-dsi-t-clk-post = <0x0f>;
qcom,mdss-dsi-t-clk-pre = <0x36>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
index 5088f0f..7812a48 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
@@ -97,8 +97,6 @@
1 5 9 13>;
qcom,sde-sspp-excl-rect = <1 1 1 1
1 1 1 1>;
- qcom,sde-sspp-smart-dma-priority = <5 6 7 8 1 2 3 4>;
- qcom,sde-smart-dma-rev = "smart_dma_v2";
qcom,sde-mixer-pair-mask = <2 1 6 0 0 3>;
@@ -120,6 +118,7 @@
qcom,sde-highest-bank-bit = <0x2>;
qcom,sde-ubwc-version = <0x200>;
qcom,sde-ubwc-static = <0x100>;
+ qcom,sde-ubwc-swizzle = <1>;
qcom,sde-panic-per-pipe;
qcom,sde-has-cdp;
qcom,sde-has-src-split;
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 87d8a56..5660841 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -1021,6 +1021,29 @@
mbox-names = "qdss_clk";
};
+ ufs_ice: ufsice@1d90000 {
+ compatible = "qcom,ice";
+ reg = <0x1d90000 0x8000>;
+ qcom,enable-ice-clk;
+ clock-names = "ufs_core_clk", "bus_clk",
+ "iface_clk", "ice_core_clk";
+ clocks = <&clock_gcc GCC_UFS_PHY_AXI_CLK>,
+ <&clock_gcc GCC_UFS_MEM_CLKREF_CLK>,
+ <&clock_gcc GCC_UFS_PHY_AHB_CLK>,
+ <&clock_gcc GCC_UFS_PHY_ICE_CORE_CLK>;
+ qcom,op-freq-hz = <0>, <0>, <0>, <300000000>;
+ vdd-hba-supply = <&ufs_phy_gdsc>;
+ qcom,msm-bus,name = "ufs_ice_noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <1 650 0 0>, /* No vote */
+ <1 650 1000 0>; /* Max. bandwidth */
+ qcom,bus-vector-names = "MIN",
+ "MAX";
+ qcom,instance-type = "ufs";
+ };
+
ufsphy_mem: ufsphy_mem@1d87000 {
reg = <0x1d87000 0xda8>; /* PHY regs */
reg-names = "phy_mem";
@@ -1044,6 +1067,7 @@
interrupts = <0 265 0>;
phys = <&ufsphy_mem>;
phy-names = "ufsphy";
+ ufs-qcom-crypto = <&ufs_ice>;
lanes-per-direction = <2>;
dev-ref-clk-freq = <0>; /* 19.2 MHz */
@@ -2151,6 +2175,65 @@
hyplog-size-offset = <0x414>;
};
+ qcom_cedev: qcedev@1de0000 {
+ compatible = "qcom,qcedev";
+ reg = <0x1de0000 0x20000>,
+ <0x1dc4000 0x24000>;
+ reg-names = "crypto-base","crypto-bam-base";
+ interrupts = <0 272 0>;
+ qcom,bam-pipe-pair = <1>;
+ qcom,ce-hw-instance = <0>;
+ qcom,ce-device = <0>;
+ qcom,ce-hw-shared;
+ qcom,bam-ee = <0>;
+ qcom,msm-bus,name = "qcedev-noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <125 512 0 0>,
+ <125 512 393600 393600>;
+ clock-names = "core_clk_src", "core_clk",
+ "iface_clk", "bus_clk";
+ clocks = <&clock_gcc GCC_CE1_CLK>,
+ <&clock_gcc GCC_CE1_CLK>,
+ <&clock_gcc GCC_CE1_AHB_CLK>,
+ <&clock_gcc GCC_CE1_AXI_CLK>;
+ qcom,ce-opp-freq = <171430000>;
+ };
+
+ qcom_crypto: qcrypto@1de0000 {
+ compatible = "qcom,qcrypto";
+ reg = <0x1de0000 0x20000>,
+ <0x1dc4000 0x24000>;
+ reg-names = "crypto-base","crypto-bam-base";
+ interrupts = <0 272 0>;
+ qcom,bam-pipe-pair = <2>;
+ qcom,ce-hw-instance = <0>;
+ qcom,ce-device = <0>;
+ qcom,bam-ee = <0>;
+ qcom,ce-hw-shared;
+ qcom,clk-mgmt-sus-res;
+ qcom,msm-bus,name = "qcrypto-noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <125 512 0 0>,
+ <125 512 393600 393600>;
+ clock-names = "core_clk_src", "core_clk",
+ "iface_clk", "bus_clk";
+ clocks = <&clock_gcc GCC_CE1_CLK>,
+ <&clock_gcc GCC_CE1_CLK>,
+ <&clock_gcc GCC_CE1_AHB_CLK>,
+ <&clock_gcc GCC_CE1_AXI_CLK>;
+ qcom,ce-opp-freq = <171430000>;
+ qcom,use-sw-aes-cbc-ecb-ctr-algo;
+ qcom,use-sw-aes-xts-algo;
+ qcom,use-sw-aes-ccm-algo;
+ qcom,use-sw-ahash-algo;
+ qcom,use-sw-aead-algo;
+ qcom,use-sw-hmac-algo;
+ };
+
qcom,msm_gsi {
compatible = "qcom,msm_gsi";
};
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index c5cfa18..7f00787 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -336,6 +336,7 @@
CONFIG_MSM_VIDC_GOVERNORS=y
CONFIG_MSM_SDE_ROTATOR=y
CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_QCOM_KGSL=y
CONFIG_DRM=y
CONFIG_DRM_SDE_EVTLOG_DEBUG=y
CONFIG_DRM_SDE_RSC=y
@@ -445,6 +446,8 @@
CONFIG_QCOM_RUN_QUEUE_STATS=y
CONFIG_QCOM_LLCC=y
CONFIG_QCOM_SDM845_LLCC=y
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_QCOM_EUD=y
CONFIG_QCOM_WATCHDOG_V2=y
@@ -478,6 +481,7 @@
CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_PM=y
CONFIG_APSS_CORE_EA=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_ARM_MEMLAT_MON=y
CONFIG_QCOMCCI_HWMON=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 100ca68..4fdbffa 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -462,6 +462,8 @@
CONFIG_QCOM_RUN_QUEUE_STATS=y
CONFIG_QCOM_LLCC=y
CONFIG_QCOM_SDM845_LLCC=y
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_CORE_HANG_DETECT=y
CONFIG_MSM_GLADIATOR_HANG_DETECT=y
@@ -499,6 +501,7 @@
CONFIG_MSM_PM=y
CONFIG_APSS_CORE_EA=y
CONFIG_QCOM_DCC_V2=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_ARM_MEMLAT_MON=y
CONFIG_QCOMCCI_HWMON=y
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index fd02eba..f61b78a 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -385,58 +385,6 @@
Select this to offload Samsung S5PV210 or S5PC110, Exynos from AES
algorithms execution.
-config CRYPTO_DEV_QCE50
- bool
-
-config FIPS_ENABLE
- bool "FIPS140-2 compliant build"
- default n
- help
- This flag is used to make current build FIPS140-2
- compliant. This flag will enable the patch of code
- which will perform this task. Please select Y here
- to enable.
-
-config CRYPTO_DEV_QCRYPTO
- tristate "QTI Crypto accelerator"
- select CRYPTO_DES
- select CRYPTO_ALGAPI
- select CRYPTO_AUTHENC
- select CRYPTO_BLKCIPHER
- default n
- help
- This driver supports QTI crypto acceleration
- for kernel clients. To compile this driver as a module,
- choose M here: the module will be called qcrypto. Please
- select Y here to enable.
-
-config CRYPTO_DEV_QCOM_MSM_QCE
- tristate "QTI Crypto Engine (QCE) module"
- default n
- help
- This driver supports QTI Crypto Engine 5.0.
- To compile this driver as a module, choose M here: the
- module is called qce50.
-
-config CRYPTO_DEV_QCEDEV
- tristate "QCEDEV Interface to CE module"
- default n
- help
- This driver supports QTI QCEDEV Crypto Engine 5.0.
- This exposes the interface to the QCE hardware accelerator
- via IOCTLs.
-
- To compile this driver as a module, choose M here: the
- module will be called qcedev.
-
-config CRYPTO_DEV_OTA_CRYPTO
- tristate "OTA Crypto module"
- help
- This driver supports QTI OTA Crypto in the FSM9xxx.
- To compile this driver as a module, choose M here: the
- module will be called ota_crypto. Please select Y here
- to enable.
-
config CRYPTO_DEV_NX
bool "Support for IBM PowerPC Nest (NX) cryptographic acceleration"
depends on PPC64
@@ -550,7 +498,49 @@
help
This driver supports Qualcomm crypto engine accelerator
hardware. To compile this driver as a module, choose M here. The
- module will be called qcrypto.
+ module will be called qcrypt.
+
+config CRYPTO_DEV_QCOM_MSM_QCE
+ tristate "QTI Crypto Engine (QCE) module"
+ depends on ARCH_QCOM
+ help
+ This driver supports QTI Crypto Engine accelerator hardware, which
+ is present on SDM845. This is the core crypto driver which adds
+ CE5.0 functionalities. To compile this driver as a module, choose
+ M here. The module will be called QCE50.
+
+config CRYPTO_DEV_QCRYPTO
+ tristate "QTI Crypto accelerator"
+ depends on ARCH_QCOM
+ select CRYPTO_DES
+ select CRYPTO_ALGAPI
+ select CRYPTO_AUTHENC
+ select CRYPTO_BLKCIPHER
+ help
+ This driver supports QTI crypto acceleration
+ for kernel clients. To compile this driver as a module,
+ choose M here: the module will be called qcrypto. Please
+ select Y here to enable.
+
+config CRYPTO_DEV_QCEDEV
+ tristate "QCEDEV Interface to CE module"
+ depends on ARCH_QCOM
+ help
+ This driver supports QTI QCEDEV Crypto Engine 5.0.
+ This exposes the interface to the QCE hardware accelerator
+ via IOCTLs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called qcedev.
+
+config CRYPTO_DEV_OTA_CRYPTO
+ tristate "OTA Crypto module"
+ depends on ARCH_QCOM
+ help
+ This driver supports QTI OTA Crypto in the FSM9xxx.
+ To compile this driver as a module, choose M here: the
+ module will be called ota_crypto. Please select Y here
+ to enable.
config CRYPTO_DEV_VMX
bool "Support for VMX cryptographic acceleration instructions"
diff --git a/drivers/crypto/msm/Kconfig b/drivers/crypto/msm/Kconfig
index 0f4568b..3011aa6 100644
--- a/drivers/crypto/msm/Kconfig
+++ b/drivers/crypto/msm/Kconfig
@@ -2,7 +2,7 @@
config CRYPTO_DEV_QCOM_ICE
tristate "Inline Crypto Module"
default n
- depends on PFK && BLK_DEV_DM
+ depends on BLK_DEV_DM
help
This driver supports Inline Crypto Engine for QTI chipsets, MSM8994
and later, to accelerate crypto operations for storage needs.
diff --git a/drivers/crypto/msm/ice.c b/drivers/crypto/msm/ice.c
index ba6825e..b411726 100644
--- a/drivers/crypto/msm/ice.c
+++ b/drivers/crypto/msm/ice.c
@@ -21,12 +21,31 @@
#include <linux/cdev.h>
#include <linux/regulator/consumer.h>
#include <linux/msm-bus.h>
-#include <linux/pfk.h>
#include <crypto/ice.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/qseecomi.h>
#include "iceregs.h"
+#ifdef CONFIG_PFK
+#include <linux/pfk.h>
+#else
+#include <linux/bio.h>
+static inline int pfk_load_key_start(const struct bio *bio,
+ struct ice_crypto_setting *ice_setting, bool *is_pfe, bool async)
+{
+ return 0;
+}
+
+static inline int pfk_load_key_end(const struct bio *bio, bool *is_pfe)
+{
+ return 0;
+}
+
+static inline void pfk_clear_on_reset(void)
+{
+}
+#endif
+
#define TZ_SYSCALL_CREATE_SMC_ID(o, s, f) \
((uint32_t)((((o & 0x3f) << 24) | (s & 0xff) << 8) | (f & 0xff)))
diff --git a/drivers/crypto/qce/Makefile b/drivers/crypto/qce/Makefile
index 348dc31..7f584ee 100644
--- a/drivers/crypto/qce/Makefile
+++ b/drivers/crypto/qce/Makefile
@@ -1,5 +1,5 @@
-obj-$(CONFIG_CRYPTO_DEV_QCE) += qcrypto.o
-qcrypto-objs := core.o \
+obj-$(CONFIG_CRYPTO_DEV_QCE) += qcrypt.o
+qcrypt-objs := core.o \
common.o \
dma.o \
sha.o \
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 2aa966b..64e9544 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -164,6 +164,7 @@
/* enum/bitmask properties */
CONNECTOR_PROP_TOPOLOGY_NAME,
CONNECTOR_PROP_TOPOLOGY_CONTROL,
+ CONNECTOR_PROP_AUTOREFRESH,
/* total # of properties */
CONNECTOR_PROP_COUNT
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index e3f8261..9f8d7ee 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -21,6 +21,9 @@
#define BL_NODE_NAME_SIZE 32
+/* Autorefresh will occur after FRAME_CNT frames. Large values are unlikely */
+#define AUTOREFRESH_MAX_FRAME_CNT 6
+
#define SDE_DEBUG_CONN(c, fmt, ...) SDE_DEBUG("conn%d " fmt,\
(c) ? (c)->base.base.id : -1, ##__VA_ARGS__)
@@ -990,6 +993,10 @@
msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
0x0, 0, INR_OPEN_MAX, 0, CONNECTOR_PROP_RETIRE_FENCE);
+ msm_property_install_range(&c_conn->property_info, "autorefresh",
+ 0x0, 0, AUTOREFRESH_MAX_FRAME_CNT, 0,
+ CONNECTOR_PROP_AUTOREFRESH);
+
/* enum/bitmask properties */
msm_property_install_enum(&c_conn->property_info, "topology_name",
DRM_MODE_PROP_IMMUTABLE, 0, e_topology_name,
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 6bae083..f2d78cb 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -808,6 +808,44 @@
return 0;
}
+static int _sde_crtc_check_autorefresh(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ struct sde_crtc *sde_crtc;
+ struct sde_crtc_state *crtc_state;
+ struct drm_connector *conn;
+ struct drm_connector_state *conn_state;
+ int i;
+
+ if (!crtc || !state)
+ return -EINVAL;
+
+ sde_crtc = to_sde_crtc(crtc);
+ crtc_state = to_sde_crtc_state(state);
+
+ if (sde_kms_rect_is_null(&crtc_state->crtc_roi))
+ return 0;
+
+ /* partial update active, check if autorefresh is also requested */
+ for_each_connector_in_state(state->state, conn, conn_state, i) {
+ uint64_t autorefresh;
+
+ if (!conn_state || conn_state->crtc != crtc)
+ continue;
+
+ autorefresh = sde_connector_get_property(conn_state,
+ CONNECTOR_PROP_AUTOREFRESH);
+ if (autorefresh) {
+ SDE_ERROR(
+ "%s: autorefresh & partial crtc roi incompatible %llu\n",
+ sde_crtc->name, autorefresh);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int _sde_crtc_set_lm_roi(struct drm_crtc *crtc,
struct drm_crtc_state *state, int lm_idx)
{
@@ -953,6 +991,10 @@
if (rc)
return rc;
+ rc = _sde_crtc_check_autorefresh(crtc, state);
+ if (rc)
+ return rc;
+
for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) {
rc = _sde_crtc_set_lm_roi(crtc, state, lm_idx);
if (rc)
@@ -2074,6 +2116,33 @@
crtc->state = &cstate->base;
}
+static int _sde_crtc_vblank_no_lock(struct sde_crtc *sde_crtc, bool en)
+{
+ if (!sde_crtc) {
+ SDE_ERROR("invalid crtc\n");
+ return -EINVAL;
+ } else if (en && atomic_inc_return(&sde_crtc->vblank_refcount) == 1) {
+ SDE_DEBUG("crtc%d vblank enable\n", sde_crtc->base.base.id);
+ if (!sde_crtc->suspend)
+ _sde_crtc_vblank_enable_nolock(sde_crtc, true);
+ } else if (!en && atomic_read(&sde_crtc->vblank_refcount) < 1) {
+ SDE_ERROR("crtc%d invalid vblank disable\n",
+ sde_crtc->base.base.id);
+ return -EINVAL;
+ } else if (!en && atomic_dec_return(&sde_crtc->vblank_refcount) == 0) {
+ SDE_DEBUG("crtc%d vblank disable\n", sde_crtc->base.base.id);
+ if (!sde_crtc->suspend)
+ _sde_crtc_vblank_enable_nolock(sde_crtc, false);
+ } else {
+ SDE_DEBUG("crtc%d vblank %s refcount:%d\n",
+ sde_crtc->base.base.id,
+ en ? "enable" : "disable",
+ atomic_read(&sde_crtc->vblank_refcount));
+ }
+
+ return 0;
+}
+
static void sde_crtc_disable(struct drm_crtc *crtc)
{
struct sde_crtc *sde_crtc;
@@ -2103,13 +2172,9 @@
crtc->base.id);
SDE_EVT32(DRMID(crtc), atomic_read(&sde_crtc->vblank_refcount),
SDE_EVTLOG_FUNC_CASE1);
- drm_for_each_encoder(encoder, crtc->dev) {
- if (encoder->crtc != crtc)
- continue;
- sde_encoder_register_vblank_callback(encoder, NULL,
- NULL);
- }
- atomic_set(&sde_crtc->vblank_refcount, 0);
+ while (atomic_read(&sde_crtc->vblank_refcount))
+ if (_sde_crtc_vblank_no_lock(sde_crtc, false))
+ break;
}
if (atomic_read(&sde_crtc->frame_pending)) {
@@ -2463,7 +2528,7 @@
int sde_crtc_vblank(struct drm_crtc *crtc, bool en)
{
struct sde_crtc *sde_crtc;
- int rc = 0;
+ int rc;
if (!crtc) {
SDE_ERROR("invalid crtc\n");
@@ -2472,25 +2537,9 @@
sde_crtc = to_sde_crtc(crtc);
mutex_lock(&sde_crtc->crtc_lock);
- if (en && atomic_inc_return(&sde_crtc->vblank_refcount) == 1) {
- SDE_DEBUG("crtc%d vblank enable\n", crtc->base.id);
- if (!sde_crtc->suspend)
- _sde_crtc_vblank_enable_nolock(sde_crtc, true);
- } else if (!en && atomic_read(&sde_crtc->vblank_refcount) < 1) {
- SDE_ERROR("crtc%d invalid vblank disable\n", crtc->base.id);
- rc = -EINVAL;
- } else if (!en && atomic_dec_return(&sde_crtc->vblank_refcount) == 0) {
- SDE_DEBUG("crtc%d vblank disable\n", crtc->base.id);
- if (!sde_crtc->suspend)
- _sde_crtc_vblank_enable_nolock(sde_crtc, false);
- } else {
- SDE_DEBUG("crtc%d vblank %s refcount:%d\n",
- crtc->base.id,
- en ? "enable" : "disable",
- atomic_read(&sde_crtc->vblank_refcount));
- }
-
+ rc = _sde_crtc_vblank_no_lock(sde_crtc, en);
mutex_unlock(&sde_crtc->crtc_lock);
+
return rc;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 7ad0955..98ba711 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -316,6 +316,21 @@
}
/**
+ * sde_crtc_frame_pending - retun the number of pending frames
+ * @crtc: Pointer to drm crtc object
+ */
+static inline int sde_crtc_frame_pending(struct drm_crtc *crtc)
+{
+ struct sde_crtc *sde_crtc;
+
+ if (!crtc)
+ return -EINVAL;
+
+ sde_crtc = to_sde_crtc(crtc);
+ return atomic_read(&sde_crtc->frame_pending);
+}
+
+/**
* sde_crtc_vblank - enable or disable vblanks for this crtc
* @crtc: Pointer to drm crtc object
* @en: true to enable vblanks, false to disable
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 94420ed..3357642 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -34,6 +34,7 @@
#include "sde_encoder_phys.h"
#include "sde_power_handle.h"
#include "sde_hw_dsc.h"
+#include "sde_crtc.h"
#define SDE_DEBUG_ENC(e, fmt, ...) SDE_DEBUG("enc%d " fmt,\
(e) ? (e)->base.base.id : -1, ##__VA_ARGS__)
@@ -58,6 +59,56 @@
#define MISR_BUFF_SIZE 256
+#define IDLE_TIMEOUT 64
+
+/**
+ * enum sde_enc_rc_events - events for resource control state machine
+ * @SDE_ENC_RC_EVENT_KICKOFF:
+ * This event happens at NORMAL priority.
+ * Event that signals the start of the transfer. When this event is
+ * received, enable MDP/DSI core clocks and request RSC with CMD state.
+ * Regardless of the previous state, the resource should be in ON state
+ * at the end of this event.
+ * @SDE_ENC_RC_EVENT_FRAME_DONE:
+ * This event happens at INTERRUPT level.
+ * Event signals the end of the data transfer after the PP FRAME_DONE
+ * event. At the end of this event, a delayed work is scheduled to go to
+ * IDLE_PC state after IDLE_TIMEOUT time.
+ * @SDE_ENC_RC_EVENT_STOP:
+ * This event happens at NORMAL priority.
+ * When this event is received, disable all the MDP/DSI core clocks
+ * and request RSC with IDLE state. Resource state should be in OFF
+ * at the end of the event.
+ * @SDE_ENC_RC_EARLY_WAKEUP
+ * This event happens at NORMAL priority from a work item.
+ * Event signals that there will be frame update soon and the driver should
+ * wake up early to update the frame with minimum latency.
+ * @SDE_ENC_RC_EVENT_ENTER_IDLE:
+ * This event happens at NORMAL priority from a work item.
+ * Event signals that there were no frame updates for IDLE_TIMEOUT time.
+ * This would disable MDP/DSI core clocks and request RSC with IDLE state
+ * and change the resource state to IDLE.
+ */
+enum sde_enc_rc_events {
+ SDE_ENC_RC_EVENT_KICKOFF = 1,
+ SDE_ENC_RC_EVENT_FRAME_DONE,
+ SDE_ENC_RC_EVENT_STOP,
+ SDE_ENC_RC_EVENT_EARLY_WAKE_UP,
+ SDE_ENC_RC_EVENT_ENTER_IDLE
+};
+
+/*
+ * enum sde_enc_rc_states - states that the resource control maintains
+ * @SDE_ENC_RC_STATE_OFF: Resource is in OFF state
+ * @SDE_ENC_RC_STATE_ON: Resource is in ON state
+ * @SDE_ENC_RC_STATE_IDLE: Resource is in IDLE state
+ */
+enum sde_enc_rc_states {
+ SDE_ENC_RC_STATE_OFF,
+ SDE_ENC_RC_STATE_ON,
+ SDE_ENC_RC_STATE_IDLE
+};
+
/**
* struct sde_encoder_virt - virtual encoder. Container of one or more physical
* encoders. Virtual encoder manages one "logical" display. Physical
@@ -91,7 +142,16 @@
* @crtc_frame_event: callback event
* @frame_done_timeout: frame done timeout in Hz
* @frame_done_timer: watchdog timer for frame done event
+ * @rsc_client: rsc client pointer
+ * @rsc_state_init: boolean to indicate rsc config init
+ * @disp_info: local copy of msm_display_info struct
* @misr_enable: misr enable/disable status
+ * @idle_pc_supported: indicate if idle power collaps is supported
+ * @rc_lock: resource control mutex lock to protect
+ * virt encoder over various state changes
+ * @rc_state: resource controller state
+ * @delayed_off_work: delayed worker to schedule disabling of
+ * clks and resources after IDLE_TIMEOUT time.
*/
struct sde_encoder_virt {
struct drm_encoder base;
@@ -120,9 +180,14 @@
struct timer_list frame_done_timer;
struct sde_rsc_client *rsc_client;
+ bool rsc_state_init;
struct msm_display_info disp_info;
- bool rsc_state_update;
bool misr_enable;
+
+ bool idle_pc_supported;
+ struct mutex rc_lock;
+ enum sde_enc_rc_states rc_state;
+ struct delayed_work delayed_off_work;
};
#define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base)
@@ -700,6 +765,11 @@
sde_enc = to_sde_encoder_virt(drm_enc);
disp_info = &sde_enc->disp_info;
+ if (!sde_enc->rsc_client) {
+ SDE_DEBUG("rsc client not created\n");
+ return 0;
+ }
+
/**
* only primary command mode panel can request CMD state.
* all other panels/displays can request for VID state including
@@ -710,14 +780,14 @@
disp_info->is_primary) ? SDE_RSC_CMD_STATE :
SDE_RSC_VID_STATE) : SDE_RSC_IDLE_STATE;
- if (rsc_state != SDE_RSC_IDLE_STATE && !sde_enc->rsc_state_update
+ if (rsc_state != SDE_RSC_IDLE_STATE && !sde_enc->rsc_state_init
&& disp_info->is_primary) {
rsc_config.fps = disp_info->frame_rate;
rsc_config.vtotal = disp_info->vtotal;
rsc_config.prefill_lines = disp_info->prefill_lines;
rsc_config.jitter = disp_info->jitter;
/* update it only once */
- sde_enc->rsc_state_update = true;
+ sde_enc->rsc_state_init = true;
ret = sde_rsc_client_state_update(sde_enc->rsc_client,
rsc_state, &rsc_config,
@@ -748,6 +818,277 @@
return disp_info->is_primary ? sde_enc->rsc_client : NULL;
}
+static void _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc,
+ bool enable)
+{
+ struct msm_drm_private *priv;
+ struct sde_kms *sde_kms;
+ struct sde_encoder_virt *sde_enc;
+ int i;
+
+ sde_enc = to_sde_encoder_virt(drm_enc);
+ priv = drm_enc->dev->dev_private;
+ sde_kms = to_sde_kms(priv->kms);
+
+ SDE_DEBUG_ENC(sde_enc, "enable:%d\n", enable);
+ SDE_EVT32(DRMID(drm_enc), enable);
+
+ if (!sde_enc->cur_master) {
+ SDE_ERROR("encoder master not set\n");
+ return;
+ }
+
+ if (enable) {
+ /* enable SDE core clks */
+ sde_power_resource_enable(&priv->phandle,
+ sde_kms->core_client, true);
+
+ /* enable DSI clks */
+ sde_connector_clk_ctrl(sde_enc->cur_master->connector, true);
+
+ /* enable all the irq */
+ for (i = 0; i < sde_enc->num_phys_encs; i++) {
+ struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
+
+ if (phys && phys->ops.irq_control)
+ phys->ops.irq_control(phys, true);
+ }
+
+ /* enable RSC */
+ sde_encoder_update_rsc_client(drm_enc, true);
+
+ } else {
+
+ /* disable RSC */
+ sde_encoder_update_rsc_client(drm_enc, false);
+
+ /* disable all the irq */
+ for (i = 0; i < sde_enc->num_phys_encs; i++) {
+ struct sde_encoder_phys *phys =
+ sde_enc->phys_encs[i];
+
+ if (phys && phys->ops.irq_control)
+ phys->ops.irq_control(phys, false);
+ }
+
+ /* disable DSI clks */
+ sde_connector_clk_ctrl(sde_enc->cur_master->connector, false);
+
+ /* disable SDE core clks */
+ sde_power_resource_enable(&priv->phandle,
+ sde_kms->core_client, false);
+ }
+
+}
+
+static int sde_encoder_resource_control(struct drm_encoder *drm_enc,
+ u32 sw_event)
+{
+ bool schedule_off = false;
+ struct sde_encoder_virt *sde_enc;
+
+ if (!drm_enc || !drm_enc->dev || !drm_enc->dev->dev_private) {
+ SDE_ERROR("invalid parameters\n");
+ return -EINVAL;
+ }
+ sde_enc = to_sde_encoder_virt(drm_enc);
+
+ /*
+ * when idle_pc is not supported, process only KICKOFF and STOP
+ * event and return early for other events (ie video mode).
+ */
+ if (!sde_enc->idle_pc_supported &&
+ (sw_event != SDE_ENC_RC_EVENT_KICKOFF &&
+ sw_event != SDE_ENC_RC_EVENT_STOP))
+ return 0;
+
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, idle_pc_supported:%d\n", sw_event,
+ sde_enc->idle_pc_supported);
+ SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->idle_pc_supported,
+ sde_enc->rc_state, SDE_EVTLOG_FUNC_ENTRY);
+
+ switch (sw_event) {
+ case SDE_ENC_RC_EVENT_KICKOFF:
+ /* cancel delayed off work, if any */
+ if (cancel_delayed_work_sync(&sde_enc->delayed_off_work))
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work cancelled\n",
+ sw_event);
+
+ mutex_lock(&sde_enc->rc_lock);
+
+ /* return if the resource control is already in ON state */
+ if (sde_enc->rc_state == SDE_ENC_RC_STATE_ON) {
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, rc in ON state\n",
+ sw_event);
+ mutex_unlock(&sde_enc->rc_lock);
+ return 0;
+ }
+
+ /* enable all the clks and resources */
+ _sde_encoder_resource_control_helper(drm_enc, true);
+
+ SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+ SDE_ENC_RC_STATE_ON, SDE_EVTLOG_FUNC_CASE1);
+ sde_enc->rc_state = SDE_ENC_RC_STATE_ON;
+
+ mutex_unlock(&sde_enc->rc_lock);
+ break;
+
+ case SDE_ENC_RC_EVENT_FRAME_DONE:
+ /*
+ * mutex lock is not used as this event happens at interrupt
+ * context. And locking is not required as, the other events
+ * like KICKOFF and STOP does a wait-for-idle before executing
+ * the resource_control
+ */
+ if (sde_enc->rc_state != SDE_ENC_RC_STATE_ON) {
+ SDE_ERROR_ENC(sde_enc, "sw_event:%d,rc:%d-unexpected\n",
+ sw_event, sde_enc->rc_state);
+ return -EINVAL;
+ }
+
+ /*
+ * schedule off work item only when there are no
+ * frames pending
+ */
+ if (sde_crtc_frame_pending(drm_enc->crtc) > 1) {
+ SDE_DEBUG_ENC(sde_enc, "skip schedule work");
+ return 0;
+ }
+
+ /* schedule delayed off work */
+ schedule_delayed_work(&sde_enc->delayed_off_work,
+ msecs_to_jiffies(IDLE_TIMEOUT));
+ SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+ SDE_EVTLOG_FUNC_CASE2);
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work scheduled\n",
+ sw_event);
+ break;
+
+ case SDE_ENC_RC_EVENT_STOP:
+ /* cancel delayed off work, if any */
+ if (cancel_delayed_work_sync(&sde_enc->delayed_off_work))
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work cancelled\n",
+ sw_event);
+
+ mutex_lock(&sde_enc->rc_lock);
+
+ /* return if the resource control is already in OFF state */
+ if (sde_enc->rc_state == SDE_ENC_RC_STATE_OFF) {
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, rc in OFF state\n",
+ sw_event);
+ mutex_unlock(&sde_enc->rc_lock);
+ return 0;
+ }
+
+ /*
+ * disable the clks and resources only if the resource control
+ * is in ON state, otherwise the clks and resources would have
+ * been disabled while going into IDLE state
+ */
+ if (sde_enc->rc_state == SDE_ENC_RC_STATE_ON)
+ _sde_encoder_resource_control_helper(drm_enc, false);
+
+ SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+ SDE_ENC_RC_STATE_OFF, SDE_EVTLOG_FUNC_CASE3);
+ sde_enc->rc_state = SDE_ENC_RC_STATE_OFF;
+
+ mutex_unlock(&sde_enc->rc_lock);
+ break;
+
+ case SDE_ENC_RC_EVENT_EARLY_WAKE_UP:
+ /* cancel delayed off work, if any */
+ if (cancel_delayed_work_sync(&sde_enc->delayed_off_work)) {
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work cancelled\n",
+ sw_event);
+ schedule_off = true;
+ }
+
+ mutex_lock(&sde_enc->rc_lock);
+
+ SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+ schedule_off, SDE_EVTLOG_FUNC_CASE4);
+
+ /* return if the resource control is in OFF state */
+ if (sde_enc->rc_state == SDE_ENC_RC_STATE_OFF) {
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, rc in OFF state\n",
+ sw_event);
+ mutex_unlock(&sde_enc->rc_lock);
+ return 0;
+ }
+
+ /*
+ * enable all the clks and resources if resource control is
+ * coming out of IDLE state
+ */
+ if (sde_enc->rc_state == SDE_ENC_RC_STATE_IDLE) {
+ _sde_encoder_resource_control_helper(drm_enc, true);
+ sde_enc->rc_state = SDE_ENC_RC_STATE_ON;
+ schedule_off = true;
+ }
+
+ /*
+ * schedule off work when there are no frames pending and
+ * 1. early wakeup cancelled off work
+ * 2. early wakeup changed the rc_state to ON - this is to
+ * handle cases where early wakeup is called but no
+ * frame updates
+ */
+ if (schedule_off && !sde_crtc_frame_pending(drm_enc->crtc)) {
+ /* schedule delayed off work */
+ schedule_delayed_work(&sde_enc->delayed_off_work,
+ msecs_to_jiffies(IDLE_TIMEOUT));
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work scheduled\n",
+ sw_event);
+ }
+
+ mutex_unlock(&sde_enc->rc_lock);
+ break;
+
+ case SDE_ENC_RC_EVENT_ENTER_IDLE:
+ mutex_lock(&sde_enc->rc_lock);
+
+ if (sde_enc->rc_state != SDE_ENC_RC_STATE_ON) {
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, rc:%d !ON state\n",
+ sw_event, sde_enc->rc_state);
+ mutex_unlock(&sde_enc->rc_lock);
+ return 0;
+ }
+
+ /* disable all the clks and resources */
+ _sde_encoder_resource_control_helper(drm_enc, false);
+ SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+ SDE_ENC_RC_STATE_IDLE, SDE_EVTLOG_FUNC_CASE5);
+ sde_enc->rc_state = SDE_ENC_RC_STATE_IDLE;
+
+ mutex_unlock(&sde_enc->rc_lock);
+ break;
+
+ default:
+ SDE_ERROR("unexpected sw_event: %d\n", sw_event);
+ break;
+ }
+
+ SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->idle_pc_supported,
+ sde_enc->rc_state, SDE_EVTLOG_FUNC_EXIT);
+ return 0;
+}
+
+static void sde_encoder_off_work(struct work_struct *work)
+{
+ struct delayed_work *dw = to_delayed_work(work);
+ struct sde_encoder_virt *sde_enc = container_of(dw,
+ struct sde_encoder_virt, delayed_off_work);
+
+ if (!sde_enc) {
+ SDE_ERROR("invalid sde encoder\n");
+ return;
+ }
+
+ sde_encoder_resource_control(&sde_enc->base,
+ SDE_ENC_RC_EVENT_ENTER_IDLE);
+}
+
static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
struct drm_display_mode *mode,
struct drm_display_mode *adj_mode)
@@ -859,31 +1200,37 @@
SDE_DEBUG_ENC(sde_enc, "\n");
SDE_EVT32(DRMID(drm_enc));
- ret = _sde_encoder_power_enable(sde_enc, true);
- if (ret)
- return;
-
sde_enc->cur_master = NULL;
+ for (i = 0; i < sde_enc->num_phys_encs; i++) {
+ struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
+
+ if (phys && phys->ops.is_master && phys->ops.is_master(phys)) {
+ SDE_DEBUG_ENC(sde_enc, "master is now idx %d\n", i);
+ sde_enc->cur_master = phys;
+ break;
+ }
+ }
+
+ if (!sde_enc->cur_master) {
+ SDE_ERROR("virt encoder has no master! num_phys %d\n", i);
+ return;
+ }
+
+ ret = sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_KICKOFF);
+ if (ret) {
+ SDE_ERROR_ENC(sde_enc, "sde resource control failed: %d\n",
+ ret);
+ return;
+ }
for (i = 0; i < sde_enc->num_phys_encs; i++) {
struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
- if (phys) {
- if (phys->ops.is_master && phys->ops.is_master(phys)) {
- SDE_DEBUG_ENC(sde_enc,
- "master is now idx %d\n", i);
- sde_enc->cur_master = phys;
- } else if (phys->ops.enable) {
- phys->ops.enable(phys);
- }
- }
+ if (phys && (phys != sde_enc->cur_master) && phys->ops.enable)
+ phys->ops.enable(phys);
}
- sde_encoder_update_rsc_client(drm_enc, true);
-
- if (!sde_enc->cur_master)
- SDE_ERROR("virt encoder has no master! num_phys %d\n", i);
- else if (sde_enc->cur_master->ops.enable)
+ if (sde_enc->cur_master && sde_enc->cur_master->ops.enable)
sde_enc->cur_master->ops.enable(sde_enc->cur_master);
if (sde_enc->cur_master && sde_enc->cur_master->hw_mdptop &&
@@ -929,9 +1276,8 @@
for (i = 0; i < sde_enc->num_phys_encs; i++) {
struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
- if (phys) {
- if (phys->ops.disable && !phys->ops.is_master(phys))
- phys->ops.disable(phys);
+ if (phys && phys->ops.disable && !phys->ops.is_master(phys)) {
+ phys->ops.disable(phys);
phys->connector = NULL;
}
}
@@ -942,17 +1288,19 @@
del_timer_sync(&sde_enc->frame_done_timer);
}
- sde_encoder_update_rsc_client(drm_enc, false);
-
if (sde_enc->cur_master && sde_enc->cur_master->ops.disable)
sde_enc->cur_master->ops.disable(sde_enc->cur_master);
- sde_enc->cur_master = NULL;
- SDE_DEBUG_ENC(sde_enc, "cleared master\n");
+ sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_STOP);
+
+ if (sde_enc->cur_master) {
+ sde_enc->cur_master->connector = NULL;
+ sde_enc->cur_master = NULL;
+ }
+
+ SDE_DEBUG_ENC(sde_enc, "encoder disabled\n");
sde_rm_release(&sde_kms->rm, drm_enc);
-
- _sde_encoder_power_enable(sde_enc, false);
}
static enum sde_intf sde_encoder_get_intf(struct sde_mdss_cfg *catalog,
@@ -1081,6 +1429,9 @@
atomic_set(&sde_enc->frame_done_timeout, 0);
del_timer(&sde_enc->frame_done_timer);
+ sde_encoder_resource_control(drm_enc,
+ SDE_ENC_RC_EVENT_FRAME_DONE);
+
if (sde_enc->crtc_frame_event_cb)
sde_enc->crtc_frame_event_cb(
sde_enc->crtc_frame_event_cb_data,
@@ -1323,6 +1674,8 @@
}
}
+ sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_KICKOFF);
+
/* if any phys needs reset, reset all phys, in-order */
if (needs_hw_reset) {
for (i = 0; i < sde_enc->num_phys_encs; i++) {
@@ -1813,6 +2166,9 @@
phys_params.comp_type = disp_info->comp_info.comp_type;
+ if (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE)
+ sde_enc->idle_pc_supported = sde_kms->catalog->has_idle_pc;
+
mutex_lock(&sde_enc->enc_lock);
for (i = 0; i < disp_info->num_of_h_tiles && !ret; i++) {
/*
@@ -1973,6 +2329,9 @@
sde_enc->rsc_client = NULL;
}
+ mutex_init(&sde_enc->rc_lock);
+ INIT_DELAYED_WORK(&sde_enc->delayed_off_work, sde_encoder_off_work);
+
memcpy(&sde_enc->disp_info, disp_info, sizeof(*disp_info));
SDE_DEBUG_ENC(sde_enc, "created\n");
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
index da155b0..6942292 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
@@ -117,6 +117,7 @@
* @collect_misr: Collects MISR data on frame update
* @hw_reset: Issue HW recovery such as CTL reset and clear
* SDE_ENC_ERR_NEEDS_HW_RESET state
+ * @irq_control: Handler to enable/disable all the encoder IRQs
*/
struct sde_encoder_phys_ops {
@@ -150,6 +151,7 @@
bool enable, u32 frame_count);
u32 (*collect_misr)(struct sde_encoder_phys *phys_enc);
void (*hw_reset)(struct sde_encoder_phys *phys_enc);
+ void (*irq_control)(struct sde_encoder_phys *phys, bool enable);
};
/**
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
index 5b59828..a4f40f2 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -363,6 +363,78 @@
return 0;
}
+static int sde_encoder_phys_cmd_control_vblank_irq(
+ struct sde_encoder_phys *phys_enc,
+ bool enable)
+{
+ struct sde_encoder_phys_cmd *cmd_enc =
+ to_sde_encoder_phys_cmd(phys_enc);
+ int ret = 0;
+
+ if (!phys_enc) {
+ SDE_ERROR("invalid encoder\n");
+ return -EINVAL;
+ }
+
+ /* Slave encoders don't report vblank */
+ if (!sde_encoder_phys_cmd_is_master(phys_enc))
+ goto end;
+
+ SDE_DEBUG_CMDENC(cmd_enc, "[%pS] enable=%d/%d\n",
+ __builtin_return_address(0),
+ enable, atomic_read(&phys_enc->vblank_refcount));
+
+ SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
+ enable, atomic_read(&phys_enc->vblank_refcount));
+
+ if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
+ ret = sde_encoder_phys_cmd_register_irq(phys_enc,
+ SDE_IRQ_TYPE_PING_PONG_RD_PTR,
+ INTR_IDX_RDPTR,
+ sde_encoder_phys_cmd_pp_rd_ptr_irq,
+ "pp_rd_ptr");
+ else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0)
+ ret = sde_encoder_phys_cmd_unregister_irq(phys_enc,
+ INTR_IDX_RDPTR);
+
+end:
+ if (ret)
+ SDE_ERROR_CMDENC(cmd_enc,
+ "control vblank irq error %d, enable %d\n",
+ ret, enable);
+
+ return ret;
+}
+
+void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc,
+ bool enable)
+{
+ if (!phys_enc || _sde_encoder_phys_is_ppsplit_slave(phys_enc))
+ return;
+
+ if (enable) {
+ sde_encoder_phys_cmd_register_irq(phys_enc,
+ SDE_IRQ_TYPE_PING_PONG_COMP,
+ INTR_IDX_PINGPONG,
+ sde_encoder_phys_cmd_pp_tx_done_irq,
+ "pp_tx_done");
+
+ sde_encoder_phys_cmd_control_vblank_irq(phys_enc, true);
+
+ sde_encoder_phys_cmd_register_irq(phys_enc,
+ SDE_IRQ_TYPE_INTF_UNDER_RUN,
+ INTR_IDX_UNDERRUN,
+ sde_encoder_phys_cmd_underrun_irq,
+ "underrun");
+ } else {
+ sde_encoder_phys_cmd_unregister_irq(
+ phys_enc, INTR_IDX_UNDERRUN);
+ sde_encoder_phys_cmd_control_vblank_irq(phys_enc, false);
+ sde_encoder_phys_cmd_unregister_irq(
+ phys_enc, INTR_IDX_PINGPONG);
+ }
+}
+
static void sde_encoder_phys_cmd_tearcheck_config(
struct sde_encoder_phys *phys_enc)
{
@@ -477,56 +549,12 @@
return _sde_encoder_phys_is_ppsplit(phys_enc);
}
-static int sde_encoder_phys_cmd_control_vblank_irq(
- struct sde_encoder_phys *phys_enc,
- bool enable)
-{
- struct sde_encoder_phys_cmd *cmd_enc =
- to_sde_encoder_phys_cmd(phys_enc);
- int ret = 0;
-
- if (!phys_enc) {
- SDE_ERROR("invalid encoder\n");
- return -EINVAL;
- }
-
- /* Slave encoders don't report vblank */
- if (!sde_encoder_phys_cmd_is_master(phys_enc))
- goto end;
-
- SDE_DEBUG_CMDENC(cmd_enc, "[%pS] enable=%d/%d\n",
- __builtin_return_address(0),
- enable, atomic_read(&phys_enc->vblank_refcount));
-
- SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
- enable, atomic_read(&phys_enc->vblank_refcount));
-
- if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
- ret = sde_encoder_phys_cmd_register_irq(phys_enc,
- SDE_IRQ_TYPE_PING_PONG_RD_PTR,
- INTR_IDX_RDPTR,
- sde_encoder_phys_cmd_pp_rd_ptr_irq,
- "pp_rd_ptr");
- else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0)
- ret = sde_encoder_phys_cmd_unregister_irq(phys_enc,
- INTR_IDX_RDPTR);
-
-end:
- if (ret)
- SDE_ERROR_CMDENC(cmd_enc,
- "control vblank irq error %d, enable %d\n",
- ret, enable);
-
- return ret;
-}
-
static void sde_encoder_phys_cmd_enable(struct sde_encoder_phys *phys_enc)
{
struct sde_encoder_phys_cmd *cmd_enc =
to_sde_encoder_phys_cmd(phys_enc);
struct sde_hw_ctl *ctl;
u32 flush_mask = 0;
- int ret;
if (!phys_enc || !phys_enc->hw_ctl) {
SDE_ERROR("invalid arg(s), encoder %d\n", phys_enc != 0);
@@ -543,38 +571,6 @@
sde_encoder_phys_cmd_pingpong_config(phys_enc);
- if (_sde_encoder_phys_is_ppsplit_slave(phys_enc))
- goto update_flush;
-
- /* Both master and slave need to register for pp_tx_done */
- ret = sde_encoder_phys_cmd_register_irq(phys_enc,
- SDE_IRQ_TYPE_PING_PONG_COMP,
- INTR_IDX_PINGPONG,
- sde_encoder_phys_cmd_pp_tx_done_irq,
- "pp_tx_done");
- if (ret)
- return;
-
- ret = sde_encoder_phys_cmd_control_vblank_irq(phys_enc, true);
- if (ret) {
- sde_encoder_phys_cmd_unregister_irq(phys_enc,
- INTR_IDX_PINGPONG);
- return;
- }
-
- ret = sde_encoder_phys_cmd_register_irq(phys_enc,
- SDE_IRQ_TYPE_INTF_UNDER_RUN,
- INTR_IDX_UNDERRUN,
- sde_encoder_phys_cmd_underrun_irq,
- "underrun");
- if (ret) {
- sde_encoder_phys_cmd_control_vblank_irq(phys_enc, false);
- sde_encoder_phys_cmd_unregister_irq(phys_enc,
- INTR_IDX_PINGPONG);
- return;
- }
-
-update_flush:
ctl = phys_enc->hw_ctl;
ctl->ops.get_bitmask_intf(ctl, &flush_mask, cmd_enc->intf_idx);
ctl->ops.update_pending_flush(ctl, flush_mask);
@@ -613,21 +609,9 @@
SDE_EVT32(DRMID(phys_enc->parent),
phys_enc->hw_pp->idx - PINGPONG_0, ret);
}
-
- sde_encoder_phys_cmd_unregister_irq(
- phys_enc, INTR_IDX_UNDERRUN);
- sde_encoder_phys_cmd_control_vblank_irq(phys_enc, false);
- sde_encoder_phys_cmd_unregister_irq(
- phys_enc, INTR_IDX_PINGPONG);
}
phys_enc->enable_state = SDE_ENC_DISABLED;
-
- if (atomic_read(&phys_enc->vblank_refcount))
- SDE_ERROR("enc:%d role:%d invalid vblank refcount %d\n",
- phys_enc->parent->base.id,
- phys_enc->split_role,
- atomic_read(&phys_enc->vblank_refcount));
}
static void sde_encoder_phys_cmd_destroy(struct sde_encoder_phys *phys_enc)
@@ -723,6 +707,7 @@
ops->trigger_start = sde_encoder_helper_trigger_start;
ops->needs_single_flush = sde_encoder_phys_cmd_needs_single_flush;
ops->hw_reset = sde_encoder_helper_hw_reset;
+ ops->irq_control = sde_encoder_phys_cmd_irq_control;
}
struct sde_encoder_phys *sde_encoder_phys_cmd_init(
diff --git a/drivers/gpu/drm/msm/sde/sde_formats.c b/drivers/gpu/drm/msm/sde/sde_formats.c
index e7f3df7..c3477b5 100644
--- a/drivers/gpu/drm/msm/sde/sde_formats.c
+++ b/drivers/gpu/drm/msm/sde/sde_formats.c
@@ -1072,7 +1072,8 @@
DRM_ERROR("invalid handle for plane %d\n", i);
return -EINVAL;
}
- bos_total_size += bos[i]->size;
+ if ((i == 0) || (bos[i] != bos[0]))
+ bos_total_size += bos[i]->size;
}
if (bos_total_size < layout.total_size) {
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index cfa3b5e..b8ab066 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -120,6 +120,7 @@
SRC_SPLIT,
DIM_LAYER,
SMART_DMA_REV,
+ IDLE_PC,
SDE_PROP_MAX,
};
@@ -313,6 +314,7 @@
{SRC_SPLIT, "qcom,sde-has-src-split", false, PROP_TYPE_BOOL},
{DIM_LAYER, "qcom,sde-has-dim-layer", false, PROP_TYPE_BOOL},
{SMART_DMA_REV, "qcom,sde-smart-dma-rev", false, PROP_TYPE_STRING},
+ {IDLE_PC, "qcom,sde-has-idle-pc", false, PROP_TYPE_BOOL},
};
static struct sde_prop_type sde_perf_prop[] = {
@@ -2214,6 +2216,7 @@
cfg->has_src_split = PROP_VALUE_ACCESS(prop_value, SRC_SPLIT, 0);
cfg->has_dim_layer = PROP_VALUE_ACCESS(prop_value, DIM_LAYER, 0);
+ cfg->has_idle_pc = PROP_VALUE_ACCESS(prop_value, IDLE_PC, 0);
end:
kfree(prop_value);
return rc;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
index 97da08f..b5f83ad 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
@@ -713,6 +713,7 @@
* @ubwc_version UBWC feature version (0x0 for not supported)
* @has_sbuf indicate if stream buffer is available
* @sbuf_headroom stream buffer headroom in lines
+ * @has_idle_pc indicate if idle power collapse feature is supported
* @dma_formats Supported formats for dma pipe
* @cursor_formats Supported formats for cursor pipe
* @vig_formats Supported formats for vig pipe
@@ -735,6 +736,7 @@
u32 ubwc_version;
bool has_sbuf;
u32 sbuf_headroom;
+ bool has_idle_pc;
u32 mdss_count;
struct sde_mdss_base_cfg mdss[MAX_BLOCKS];
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_dspp.c b/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
index f1b9c32..8df4de2 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
@@ -25,6 +25,9 @@
{
int i;
+ if (!m || !addr || !b)
+ return ERR_PTR(-EINVAL);
+
for (i = 0; i < m->dspp_count; i++) {
if (dspp == m->dspp[i].id) {
b->base_off = addr;
@@ -43,6 +46,9 @@
{
int i = 0, ret;
+ if (!c || !c->cap || !c->cap->sblk)
+ return;
+
for (i = 0; i < SDE_DSPP_MAX; i++) {
if (!test_bit(i, &features))
continue;
@@ -119,6 +125,9 @@
struct sde_hw_dspp *c;
struct sde_dspp_cfg *cfg;
+ if (!addr || !m)
+ return ERR_PTR(-EINVAL);
+
c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_dspp.h b/drivers/gpu/drm/msm/sde/sde_hw_dspp.h
index 6020476..70b3e56 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_dspp.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_dspp.h
@@ -192,6 +192,7 @@
* should be called once before accessing every dspp.
* @idx: DSPP index for which driver object is required
* @addr: Mapped register io address of MDP
+ * @Return: pointer to structure or ERR_PTR
*/
struct sde_hw_dspp *sde_hw_dspp_init(enum sde_dspp idx,
void __iomem *addr,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c
index 6a91a65..24f16c6 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c
@@ -31,9 +31,9 @@
#define MDP_INTF_4_OFF 0x6D000
#define MDP_AD4_0_OFF 0x7D000
#define MDP_AD4_1_OFF 0x7E000
-#define MDP_AD4_INTR_EN_OFF 0x41c
-#define MDP_AD4_INTR_CLEAR_OFF 0x424
-#define MDP_AD4_INTR_STATUS_OFF 0x420
+#define MDP_AD4_INTR_EN_OFF 0x41c
+#define MDP_AD4_INTR_CLEAR_OFF 0x424
+#define MDP_AD4_INTR_STATUS_OFF 0x420
/**
* WB interrupt status bit definitions
@@ -87,7 +87,7 @@
* Pingpong Secondary interrupt status bit definitions
*/
#define SDE_INTR_PING_PONG_S0_AUTOREFRESH_DONE BIT(0)
-#define SDE_INTR_PING_PONG_S0_WR_PTR BIT(4)
+#define SDE_INTR_PING_PONG_S0_WR_PTR BIT(4)
#define SDE_INTR_PING_PONG_S0_RD_PTR BIT(8)
#define SDE_INTR_PING_PONG_S0_TEAR_DETECTED BIT(22)
#define SDE_INTR_PING_PONG_S0_TE_DETECTED BIT(28)
@@ -711,6 +711,9 @@
static void sde_hw_intr_set_mask(struct sde_hw_intr *intr, uint32_t reg_off,
uint32_t mask)
{
+ if (!intr)
+ return;
+
SDE_REG_WRITE(&intr->hw, reg_off, mask);
}
@@ -725,6 +728,9 @@
u32 irq_status;
unsigned long irq_flags;
+ if (!intr)
+ return;
+
/*
* The dispatcher will save the IRQ status before calling here.
* Now need to go through each IRQ status and find matching
@@ -741,6 +747,10 @@
start_idx = reg_idx * 32;
end_idx = start_idx + 32;
+ if (start_idx >= ARRAY_SIZE(sde_irq_map) ||
+ end_idx > ARRAY_SIZE(sde_irq_map))
+ continue;
+
/*
* Search through matching intr status from irq map.
* start_idx and end_idx defined the search range in
@@ -784,6 +794,9 @@
const char *dbgstr = NULL;
uint32_t cache_irq_mask;
+ if (!intr)
+ return -EINVAL;
+
if (irq_idx < 0 || irq_idx >= ARRAY_SIZE(sde_irq_map)) {
pr_err("invalid IRQ index: [%d]\n", irq_idx);
return -EINVAL;
@@ -825,6 +838,9 @@
const char *dbgstr = NULL;
uint32_t cache_irq_mask;
+ if (!intr)
+ return -EINVAL;
+
if (irq_idx < 0 || irq_idx >= ARRAY_SIZE(sde_irq_map)) {
pr_err("invalid IRQ index: [%d]\n", irq_idx);
return -EINVAL;
@@ -861,6 +877,9 @@
{
int i;
+ if (!intr)
+ return -EINVAL;
+
for (i = 0; i < ARRAY_SIZE(sde_intr_set); i++)
SDE_REG_WRITE(&intr->hw, sde_intr_set[i].clr_off, 0xffffffff);
@@ -871,6 +890,9 @@
{
int i;
+ if (!intr)
+ return -EINVAL;
+
for (i = 0; i < ARRAY_SIZE(sde_intr_set); i++)
SDE_REG_WRITE(&intr->hw, sde_intr_set[i].en_off, 0x00000000);
@@ -880,15 +902,23 @@
static int sde_hw_intr_get_valid_interrupts(struct sde_hw_intr *intr,
uint32_t *mask)
{
+ if (!intr || !mask)
+ return -EINVAL;
+
*mask = IRQ_SOURCE_MDP | IRQ_SOURCE_DSI0 | IRQ_SOURCE_DSI1
| IRQ_SOURCE_HDMI | IRQ_SOURCE_EDP;
+
return 0;
}
static int sde_hw_intr_get_interrupt_sources(struct sde_hw_intr *intr,
uint32_t *sources)
{
+ if (!intr || !sources)
+ return -EINVAL;
+
*sources = SDE_REG_READ(&intr->hw, HW_INTR_STATUS);
+
return 0;
}
@@ -898,6 +928,9 @@
u32 enable_mask;
unsigned long irq_flags;
+ if (!intr)
+ return;
+
spin_lock_irqsave(&intr->status_lock, irq_flags);
for (i = 0; i < ARRAY_SIZE(sde_intr_set); i++) {
/* Read interrupt status */
@@ -924,6 +957,9 @@
int reg_idx;
unsigned long irq_flags;
+ if (!intr)
+ return;
+
spin_lock_irqsave(&intr->mask_lock, irq_flags);
reg_idx = sde_irq_map[irq_idx].reg_idx;
@@ -940,6 +976,9 @@
unsigned long irq_flags;
u32 intr_status;
+ if (!intr)
+ return 0;
+
spin_lock_irqsave(&intr->mask_lock, irq_flags);
reg_idx = sde_irq_map[irq_idx].reg_idx;
@@ -974,7 +1013,7 @@
static struct sde_mdss_base_cfg *__intr_offset(struct sde_mdss_cfg *m,
void __iomem *addr, struct sde_hw_blk_reg_map *hw)
{
- if (m->mdp_count == 0)
+ if (!m || !addr || !hw || m->mdp_count == 0)
return NULL;
hw->base_off = addr;
@@ -986,9 +1025,13 @@
struct sde_hw_intr *sde_hw_intr_init(void __iomem *addr,
struct sde_mdss_cfg *m)
{
- struct sde_hw_intr *intr = kzalloc(sizeof(*intr), GFP_KERNEL);
+ struct sde_hw_intr *intr;
struct sde_mdss_base_cfg *cfg;
+ if (!addr || !m)
+ return ERR_PTR(-EINVAL);
+
+ intr = kzalloc(sizeof(*intr), GFP_KERNEL);
if (!intr)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h
index 7991994..aaba1be 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h
@@ -25,7 +25,7 @@
#define IRQ_SOURCE_DSI1 BIT(5)
#define IRQ_SOURCE_HDMI BIT(8)
#define IRQ_SOURCE_EDP BIT(12)
-#define IRQ_SOURCE_MHL BIT(16)
+#define IRQ_SOURCE_MHL BIT(16)
/**
* sde_intr_type - HW Interrupt Type
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_top.c b/drivers/gpu/drm/msm/sde/sde_hw_top.c
index 3ba7a51..cf54611 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_top.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_top.c
@@ -39,13 +39,15 @@
static void sde_hw_setup_split_pipe(struct sde_hw_mdp *mdp,
struct split_pipe_cfg *cfg)
{
- struct sde_hw_blk_reg_map *c = &mdp->hw;
+ struct sde_hw_blk_reg_map *c;
u32 upper_pipe = 0;
u32 lower_pipe = 0;
if (!mdp || !cfg)
return;
+ c = &mdp->hw;
+
if (cfg->en) {
if (cfg->mode == INTF_MODE_CMD) {
lower_pipe = FLD_SPLIT_DISPLAY_CMD;
@@ -107,9 +109,14 @@
static void sde_hw_setup_cdm_output(struct sde_hw_mdp *mdp,
struct cdm_output_cfg *cfg)
{
- struct sde_hw_blk_reg_map *c = &mdp->hw;
+ struct sde_hw_blk_reg_map *c;
u32 out_ctl = 0;
+ if (!mdp || !cfg)
+ return;
+
+ c = &mdp->hw;
+
if (cfg->wb_en)
out_ctl |= BIT(24);
else if (cfg->intf_en)
@@ -121,11 +128,16 @@
static bool sde_hw_setup_clk_force_ctrl(struct sde_hw_mdp *mdp,
enum sde_clk_ctrl_type clk_ctrl, bool enable)
{
- struct sde_hw_blk_reg_map *c = &mdp->hw;
+ struct sde_hw_blk_reg_map *c;
u32 reg_off, bit_off;
u32 reg_val, new_val;
bool clk_forced_on;
+ if (!mdp)
+ return false;
+
+ c = &mdp->hw;
+
if (clk_ctrl <= SDE_CLK_CTRL_NONE || clk_ctrl >= SDE_CLK_CTRL_MAX)
return false;
@@ -150,9 +162,14 @@
static void sde_hw_get_danger_status(struct sde_hw_mdp *mdp,
struct sde_danger_safe_status *status)
{
- struct sde_hw_blk_reg_map *c = &mdp->hw;
+ struct sde_hw_blk_reg_map *c;
u32 value;
+ if (!mdp || !status)
+ return;
+
+ c = &mdp->hw;
+
value = SDE_REG_READ(c, DANGER_STATUS);
status->mdp = (value >> 0) & 0x3;
status->sspp[SSPP_VIG0] = (value >> 4) & 0x3;
@@ -178,9 +195,14 @@
static void sde_hw_get_safe_status(struct sde_hw_mdp *mdp,
struct sde_danger_safe_status *status)
{
- struct sde_hw_blk_reg_map *c = &mdp->hw;
+ struct sde_hw_blk_reg_map *c;
u32 value;
+ if (!mdp || !status)
+ return;
+
+ c = &mdp->hw;
+
value = SDE_REG_READ(c, SAFE_STATUS);
status->mdp = (value >> 0) & 0x1;
status->sspp[SSPP_VIG0] = (value >> 4) & 0x1;
@@ -205,7 +227,12 @@
static void sde_hw_setup_dce(struct sde_hw_mdp *mdp, u32 dce_sel)
{
- struct sde_hw_blk_reg_map *c = &mdp->hw;
+ struct sde_hw_blk_reg_map *c;
+
+ if (!mdp)
+ return;
+
+ c = &mdp->hw;
SDE_REG_WRITE(c, DCE_SEL, dce_sel);
}
@@ -246,6 +273,9 @@
{
int i;
+ if (!m || !addr || !b)
+ return ERR_PTR(-EINVAL);
+
for (i = 0; i < m->mdp_count; i++) {
if (mdp == m->mdp[i].id) {
b->base_off = addr;
diff --git a/drivers/gpu/drm/msm/sde_power_handle.h b/drivers/gpu/drm/msm/sde_power_handle.h
index b26ef9f..d753f0a 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.h
+++ b/drivers/gpu/drm/msm/sde_power_handle.h
@@ -16,9 +16,9 @@
#define MAX_CLIENT_NAME_LEN 128
-#define SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA 64000
+#define SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA 2000000000
#define SDE_POWER_HANDLE_DISABLE_BUS_AB_QUOTA 0
-#define SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA 64000
+#define SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA 2000000000
#define SDE_POWER_HANDLE_DISABLE_BUS_IB_QUOTA 0
#include <linux/sde_io_util.h>
diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c
index d762904..f35d77b 100644
--- a/drivers/gpu/drm/msm/sde_rsc.c
+++ b/drivers/gpu/drm/msm/sde_rsc.c
@@ -28,16 +28,19 @@
#include <drm/drmP.h>
#include <drm/drm_irq.h>
#include "sde_rsc_priv.h"
+#include "sde_dbg.h"
-/* this time is ~0.02ms */
-#define RSC_BACKOFF_TIME_NS 20000
+/* worst case time to execute the one tcs vote(sleep/wake) - ~1ms */
+#define TCS_CASE_EXECUTION_TIME 1064000
-/* next two values should be same based on doc */
+/* this time is ~1ms - only wake tcs in any mode */
+#define RSC_BACKOFF_TIME_NS (TCS_CASE_EXECUTION_TIME + 100)
-/* this time is ~0.2ms */
-#define RSC_MODE_THRESHOLD_TIME_IN_NS 200000
-/* this time is ~0.2ms */
-#define RSC_TIME_SLOT_0_NS 200000
+/* this time is ~1ms - only wake TCS in mode-0 */
+#define RSC_MODE_THRESHOLD_TIME_IN_NS ((TCS_CASE_EXECUTION_TIME >> 1) + 100)
+
+/* this time is ~2ms - sleep+ wake TCS in mode-1 */
+#define RSC_TIME_SLOT_0_NS ((TCS_CASE_EXECUTION_TIME * 2) + 100)
#define DEFAULT_PANEL_FPS 60
#define DEFAULT_PANEL_JITTER 5
@@ -74,6 +77,7 @@
{
struct sde_rsc_client *client;
struct sde_rsc_priv *rsc;
+ static int id;
if (!client_name) {
pr_err("client name is null- not supported\n");
@@ -83,7 +87,7 @@
return ERR_PTR(-EINVAL);
} else if (!rsc_prv_list[rsc_index]) {
pr_err("rsc not probed yet or not available\n");
- return ERR_PTR(-EINVAL);
+ return NULL;
}
rsc = rsc_prv_list[rsc_index];
@@ -95,12 +99,14 @@
strlcpy(client->name, client_name, MAX_RSC_CLIENT_NAME_LEN);
client->current_state = SDE_RSC_IDLE_STATE;
client->rsc_index = rsc_index;
+ client->id = id;
if (is_primary_client)
rsc->primary_client = client;
pr_debug("client %s rsc index:%d primary:%d\n", client_name,
rsc_index, is_primary_client);
list_add(&client->list, &rsc->client_list);
+ id++;
mutex_unlock(&rsc->client_lock);
return client;
@@ -502,6 +508,8 @@
return -EINVAL;
mutex_lock(&rsc->client_lock);
+ SDE_EVT32(caller_client->id, caller_client->current_state,
+ state, rsc->current_state, SDE_EVTLOG_FUNC_ENTRY);
caller_client->crtc_id = crtc_id;
caller_client->current_state = state;
@@ -559,14 +567,20 @@
if (rc == STATE_UPDATE_NOT_ALLOWED) {
rc = 0;
+ SDE_EVT32(caller_client->id, caller_client->current_state,
+ state, rsc->current_state, rc, SDE_EVTLOG_FUNC_CASE1);
goto clk_disable;
} else if (rc) {
pr_debug("state:%d update failed rc:%d\n", state, rc);
+ SDE_EVT32(caller_client->id, caller_client->current_state,
+ state, rsc->current_state, rc, SDE_EVTLOG_FUNC_CASE2);
goto clk_disable;
}
pr_debug("state switch successfully complete: %d\n", state);
rsc->current_state = state;
+ SDE_EVT32(caller_client->id, caller_client->current_state,
+ state, rsc->current_state, SDE_EVTLOG_FUNC_EXIT);
clk_disable:
if (rsc->current_state == SDE_RSC_IDLE_STATE)
@@ -1063,9 +1077,6 @@
pr_err("sde rsc:get display rsc failed ret:%d\n", ret);
goto sde_rsc_fail;
}
- rpmh_invalidate(rsc->disp_rsc);
- /* call flush to disable the disp rsc interrupt */
- rpmh_flush(rsc->disp_rsc);
ret = msm_dss_ioremap_byname(pdev, &rsc->wrapper_io, "wrapper");
if (ret) {
diff --git a/drivers/gpu/drm/msm/sde_rsc_hw.c b/drivers/gpu/drm/msm/sde_rsc_hw.c
index b63fbc6..c87dac4 100644
--- a/drivers/gpu/drm/msm/sde_rsc_hw.c
+++ b/drivers/gpu/drm/msm/sde_rsc_hw.c
@@ -95,6 +95,7 @@
#define SDE_RSCC_F1_QTMR_V1_CNTP_CTL 0x302C
#define MAX_CHECK_LOOPS 500
+#define POWER_CTRL_BIT_12 12
static void rsc_event_trigger(struct sde_rsc_priv *rsc, uint32_t event_type)
{
@@ -191,27 +192,27 @@
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_MEM_0_DRV0 + 0x18,
0xa138ebaa, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_MEM_0_DRV0 + 0x1c,
- 0xe0a581e1, rsc->debug_mode);
+ 0xaca581e1, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_MEM_0_DRV0 + 0x20,
- 0x82e2a2ed, rsc->debug_mode);
+ 0xe2a2ede0, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_MEM_0_DRV0 + 0x24,
- 0x88ea8a39, rsc->debug_mode);
+ 0xea8a3982, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_MEM_0_DRV0 + 0x28,
- 0xa6e9a920, rsc->debug_mode);
+ 0xa920888c, rsc->debug_mode);
/* tcs sleep sequence */
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_MEM_0_DRV0 + 0x2c,
- 0xa92089e6, rsc->debug_mode);
+ 0x89e6a6e9, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_MEM_0_DRV0 + 0x30,
- 0x89e7a7e9, rsc->debug_mode);
+ 0xa7e9a920, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_MEM_0_DRV0 + 0x34,
- 0x00000020, rsc->debug_mode);
+ 0x002079e7, rsc->debug_mode);
/* branch address */
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_CFG_BR_ADDR_0_DRV0,
- 0x29, rsc->debug_mode);
+ 0x2b, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_CFG_BR_ADDR_1_DRV0,
- 0x2f, rsc->debug_mode);
+ 0x31, rsc->debug_mode);
return 0;
}
@@ -266,7 +267,7 @@
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM0_DRV0_MODE0,
mode_0_start_addr, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM1_DRV0_MODE0,
- 0x80000010, rsc->debug_mode);
+ 0x80000000, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM2_DRV0_MODE0,
rsc->timer_config.rsc_backoff_time_ns, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM3_DRV0_MODE0,
@@ -275,7 +276,7 @@
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM0_DRV0_MODE1,
mode_1_start_addr, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM1_DRV0_MODE1,
- 0x80000010, rsc->debug_mode);
+ 0x80000000, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM2_DRV0_MODE1,
rsc->timer_config.rsc_backoff_time_ns, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM3_DRV0_MODE1,
@@ -284,9 +285,9 @@
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM0_DRV0_MODE2,
mode_2_start_addr, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM1_DRV0_MODE2,
- 0x80000010, rsc->debug_mode);
+ 0x80000000, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM2_DRV0_MODE2,
- rsc->timer_config.rsc_backoff_time_ns, rsc->debug_mode);
+ 0x0, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM3_DRV0_MODE2,
rsc->timer_config.pdc_backoff_time_ns, rsc->debug_mode);
@@ -297,6 +298,7 @@
{
int rc;
int count, wrapper_status;
+ unsigned long reg;
if (rsc->power_collapse_block)
return -EINVAL;
@@ -355,6 +357,18 @@
if (rc) {
pr_err("vdd fs is still enabled\n");
goto end;
+ } else {
+ rc = -EINVAL;
+ /* this wait is required to turn off the rscc clocks */
+ for (count = MAX_CHECK_LOOPS; count > 0; count--) {
+ reg = dss_reg_r(&rsc->wrapper_io,
+ SDE_RSCC_PWR_CTRL, rsc->debug_mode);
+ if (test_bit(POWER_CTRL_BIT_12, ®)) {
+ rc = 0;
+ break;
+ }
+ usleep_range(1, 2);
+ }
}
if ((rsc->current_state == SDE_RSC_VID_STATE) ||
@@ -458,9 +472,6 @@
0x1, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SOLVER_OVERRIDE_CTRL_DRV0,
0x0, rsc->debug_mode);
- dss_reg_w(&rsc->drv_io,
- SDE_RSC_SOLVER_SOLVER_MODES_ENABLED_DRV0, 0x7,
- rsc->debug_mode);
reg = dss_reg_r(&rsc->wrapper_io,
SDE_RSCC_WRAPPER_OVERRIDE_CTRL, rsc->debug_mode);
reg |= (BIT(0) | BIT(8));
@@ -484,9 +495,6 @@
reg &= ~(BIT(1) | BIT(0));
dss_reg_w(&rsc->wrapper_io, SDE_RSCC_WRAPPER_OVERRIDE_CTRL,
reg, rsc->debug_mode);
- dss_reg_w(&rsc->drv_io,
- SDE_RSC_SOLVER_SOLVER_MODES_ENABLED_DRV0, 0x5,
- rsc->debug_mode);
/* make sure that solver mode is override */
wmb();
@@ -501,9 +509,6 @@
reg &= ~(BIT(8) | BIT(0));
dss_reg_w(&rsc->wrapper_io, SDE_RSCC_WRAPPER_OVERRIDE_CTRL,
reg, rsc->debug_mode);
- dss_reg_w(&rsc->drv_io,
- SDE_RSC_SOLVER_SOLVER_MODES_ENABLED_DRV0, 0x5,
- rsc->debug_mode);
/* make sure that solver mode is disabled */
wmb();
break;
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index 3c3f99f..fb41f95 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -125,7 +125,7 @@
unsigned int mmu_base = 0, mmu_range = 0, cur_range;
/* enable access protection to privileged registers */
- kgsl_regwrite(device, A6XX_CP_PROTECT_CNTL, 0x00000007);
+ kgsl_regwrite(device, A6XX_CP_PROTECT_CNTL, 0x00000003);
if (mmu_prot) {
mmu_base = mmu_prot->base;
@@ -235,6 +235,9 @@
/* Set the AHB default slave response to "ERROR" */
kgsl_regwrite(device, A6XX_CP_AHB_CNTL, 0x1);
+ /* Turn on performance counters */
+ kgsl_regwrite(device, A6XX_RBBM_PERFCTR_CNTL, 0x1);
+
if (of_property_read_u32(device->pdev->dev.of_node,
"qcom,highest-bank-bit", &bit))
bit = MIN_HBB;
@@ -282,8 +285,9 @@
kgsl_regwrite(device, A6XX_UCHE_MODE_CNTL, (glbl_inv << 29) |
(mal << 23) | (bit << 21));
+ /* Set hang detection threshold to 4 million cycles (0x3FFFF*16) */
kgsl_regwrite(device, A6XX_RBBM_INTERFACE_HANG_INT_CNTL,
- (1 << 30) | 0x4000);
+ (1 << 30) | 0x3ffff);
kgsl_regwrite(device, A6XX_UCHE_CLIENT_PF, 1);
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index ab574d8..f217822 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -342,7 +342,7 @@
struct kgsl_device *device = dev_priv->device;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
int ret;
- unsigned long local;
+ unsigned int local;
local = *flags & (KGSL_CONTEXT_PREAMBLE |
KGSL_CONTEXT_NO_GMEM_ALLOC |
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 32175f5..fbff535 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -54,10 +54,21 @@
/* Read always on registers */
if (!adreno_is_a3xx(adreno_dev)) {
- adreno_readreg64(adreno_dev,
- ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO,
- ADRENO_REG_RBBM_ALWAYSON_COUNTER_HI,
- &time->ticks);
+ if (kgsl_gmu_isenabled(KGSL_DEVICE(adreno_dev))) {
+ uint32_t val_lo, val_hi;
+
+ adreno_read_gmureg(adreno_dev,
+ ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO, &val_lo);
+ adreno_read_gmureg(adreno_dev,
+ ADRENO_REG_RBBM_ALWAYSON_COUNTER_HI, &val_hi);
+
+ time->ticks = (val_lo | ((uint64_t)val_hi << 32));
+ } else {
+ adreno_readreg64(adreno_dev,
+ ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO,
+ ADRENO_REG_RBBM_ALWAYSON_COUNTER_HI,
+ &time->ticks);
+ }
/* Mask hi bits as they may be incorrect on some targets */
if (ADRENO_GPUREV(adreno_dev) >= 400 &&
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 15f68bf..8f49bc7 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1627,7 +1627,8 @@
/* If no profiling buffer was specified, clear the flag */
if (cmdobj->profiling_buf_entry == NULL)
- DRAWOBJ(cmdobj)->flags &= ~KGSL_DRAWOBJ_PROFILING;
+ DRAWOBJ(cmdobj)->flags &=
+ ~(unsigned long)KGSL_DRAWOBJ_PROFILING;
}
result = device->ftbl->queue_cmds(dev_priv, context, drawobj,
@@ -1716,7 +1717,8 @@
/* If no profiling buffer was specified, clear the flag */
if (cmdobj->profiling_buf_entry == NULL)
- DRAWOBJ(cmdobj)->flags &= ~KGSL_DRAWOBJ_PROFILING;
+ DRAWOBJ(cmdobj)->flags &=
+ ~(unsigned long)KGSL_DRAWOBJ_PROFILING;
}
result = device->ftbl->queue_cmds(dev_priv, context, drawobj,
@@ -2041,7 +2043,7 @@
unsigned long flags_requested = (VM_READ | VM_WRITE);
if (flags & KGSL_MEMFLAGS_GPUREADONLY)
- flags_requested &= ~VM_WRITE;
+ flags_requested &= ~(unsigned long)VM_WRITE;
if ((vma->vm_flags & flags_requested) == flags_requested)
return 0;
@@ -2135,7 +2137,7 @@
entry->memdesc.pagetable = pagetable;
entry->memdesc.size = (uint64_t) size;
entry->memdesc.useraddr = hostptr;
- entry->memdesc.flags |= KGSL_MEMFLAGS_USERMEM_ADDR;
+ entry->memdesc.flags |= (uint64_t)KGSL_MEMFLAGS_USERMEM_ADDR;
if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
int ret;
@@ -2166,7 +2168,7 @@
static void _setup_cache_mode(struct kgsl_mem_entry *entry,
struct vm_area_struct *vma)
{
- unsigned int mode;
+ uint64_t mode;
pgprot_t pgprot = vma->vm_page_prot;
if (pgprot_val(pgprot) == pgprot_val(pgprot_noncached(pgprot)))
@@ -2525,7 +2527,7 @@
entry->memdesc.size = 0;
/* USE_CPU_MAP is not impemented for ION. */
entry->memdesc.flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP);
- entry->memdesc.flags |= KGSL_MEMFLAGS_USERMEM_ION;
+ entry->memdesc.flags |= (uint64_t)KGSL_MEMFLAGS_USERMEM_ION;
sg_table = dma_buf_map_attachment(attach, DMA_TO_DEVICE);
@@ -3028,8 +3030,9 @@
if ((flags & KGSL_CACHEMODE_MASK) >> KGSL_CACHEMODE_SHIFT ==
KGSL_CACHEMODE_WRITETHROUGH) {
flags &= ~((uint64_t) KGSL_CACHEMODE_MASK);
- flags |= (KGSL_CACHEMODE_WRITEBACK << KGSL_CACHEMODE_SHIFT) &
- KGSL_CACHEMODE_MASK;
+ flags |= (uint64_t)((KGSL_CACHEMODE_WRITEBACK <<
+ KGSL_CACHEMODE_SHIFT) &
+ KGSL_CACHEMODE_MASK);
}
return flags;
}
@@ -3083,8 +3086,9 @@
KGSL_MAX_ALIGN >> 10);
flags &= ~((uint64_t) KGSL_MEMALIGN_MASK);
- flags |= (ilog2(KGSL_MAX_ALIGN) << KGSL_MEMALIGN_SHIFT) &
- KGSL_MEMALIGN_MASK;
+ flags |= (uint64_t)((ilog2(KGSL_MAX_ALIGN) <<
+ KGSL_MEMALIGN_SHIFT) &
+ KGSL_MEMALIGN_MASK);
}
/* For now only allow allocations up to 4G */
@@ -3975,7 +3979,8 @@
if (param->flags & KGSL_GPUOBJ_SET_INFO_TYPE) {
entry->memdesc.flags &= ~((uint64_t) KGSL_MEMTYPE_MASK);
- entry->memdesc.flags |= param->type << KGSL_MEMTYPE_SHIFT;
+ entry->memdesc.flags |= (uint64_t)(param->type <<
+ KGSL_MEMTYPE_SHIFT);
}
kgsl_mem_entry_put(entry);
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index d635519..938c96d 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -2600,7 +2600,7 @@
static const struct {
char *feature;
- int bit;
+ unsigned long bit;
} kgsl_iommu_features[] = {
{ "qcom,retention", KGSL_MMU_RETENTION },
{ "qcom,global_pt", KGSL_MMU_GLOBAL_PAGETABLE },
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index b3e2b6a..a9a3c94 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -67,7 +67,9 @@
"isense_clk",
"rbcpr_clk",
"iref_clk",
- "gmu_clk"
+ "gmu_clk",
+ "ahb_clk",
+ "cxo_clk"
};
static unsigned int ib_votes[KGSL_MAX_BUSLEVELS];
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 62ee597..6b22fd4 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -25,7 +25,7 @@
#define KGSL_PWR_ON 0xFFFF
-#define KGSL_MAX_CLKS 15
+#define KGSL_MAX_CLKS 17
#define KGSL_MAX_REGULATORS 2
#define KGSL_MAX_PWRLEVELS 10
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index 07a54d9..7636a42 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -927,8 +927,7 @@
&data->bin.ctxt_aware_target_pwrlevel))
data->bin.ctxt_aware_target_pwrlevel = 1;
- if ((data->bin.ctxt_aware_target_pwrlevel < 0) ||
- (data->bin.ctxt_aware_target_pwrlevel >
+ if ((data->bin.ctxt_aware_target_pwrlevel >
pwr->num_pwrlevels))
data->bin.ctxt_aware_target_pwrlevel = 1;
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 10b37ae..dd41e4e 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -131,8 +131,9 @@
if (align > 32)
align = 32;
- memdesc->flags &= ~KGSL_MEMALIGN_MASK;
- memdesc->flags |= (align << KGSL_MEMALIGN_SHIFT) & KGSL_MEMALIGN_MASK;
+ memdesc->flags &= ~(uint64_t)KGSL_MEMALIGN_MASK;
+ memdesc->flags |= (uint64_t)((align << KGSL_MEMALIGN_SHIFT) &
+ KGSL_MEMALIGN_MASK);
return 0;
}
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index e66f404..aac7161 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -69,6 +69,13 @@
struct dm_stats_aux stats_aux;
};
+union map_info *dm_get_rq_mapinfo(struct request *rq)
+{
+ if (rq && rq->end_io_data)
+ return &((struct dm_rq_target_io *)rq->end_io_data)->info;
+ return NULL;
+}
+
#define MINOR_ALLOCED ((void *)-1)
/*
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
index 4f5bf87..ecc62c8 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
@@ -57,6 +57,48 @@
return 0;
}
+uint32_t cam_sync_util_get_group_object_state(struct sync_table_row *table,
+ uint32_t *sync_objs,
+ uint32_t num_objs)
+{
+ int i;
+ struct sync_table_row *child_row = NULL;
+ int success_count = 0;
+ int active_count = 0;
+
+ if (!table || !sync_objs)
+ return CAM_SYNC_STATE_SIGNALED_ERROR;
+
+ /*
+ * We need to arrive at the state of the merged object based on
+ * counts of error, active and success states of all children objects
+ */
+ for (i = 0; i < num_objs; i++) {
+ child_row = table + sync_objs[i];
+ switch (child_row->state) {
+ case CAM_SYNC_STATE_SIGNALED_ERROR:
+ return CAM_SYNC_STATE_SIGNALED_ERROR;
+ case CAM_SYNC_STATE_SIGNALED_SUCCESS:
+ success_count++;
+ break;
+ case CAM_SYNC_STATE_ACTIVE:
+ active_count++;
+ break;
+ default:
+ pr_err("Invalid state of child object during merge\n");
+ return CAM_SYNC_STATE_SIGNALED_ERROR;
+ }
+ }
+
+ if (active_count)
+ return CAM_SYNC_STATE_ACTIVE;
+
+ if (success_count == num_objs)
+ return CAM_SYNC_STATE_SIGNALED_SUCCESS;
+
+ return CAM_SYNC_STATE_SIGNALED_ERROR;
+}
+
int cam_sync_init_group_object(struct sync_table_row *table,
uint32_t idx,
uint32_t *sync_objs,
@@ -113,12 +155,16 @@
row->type = CAM_SYNC_TYPE_GROUP;
row->sync_id = idx;
- row->state = CAM_SYNC_STATE_ACTIVE;
+ row->state = cam_sync_util_get_group_object_state(table,
+ sync_objs, num_objs);
row->remaining = num_objs;
init_completion(&row->signaled);
INIT_LIST_HEAD(&row->callback_list);
INIT_LIST_HEAD(&row->user_payload_list);
+ if (row->state != CAM_SYNC_STATE_ACTIVE)
+ complete_all(&row->signaled);
+
spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
return 0;
}
@@ -208,6 +254,11 @@
int i;
struct sync_table_row *row = NULL;
+ if (num_objs <= 1) {
+ pr_err("Single object merge is not allowed\n");
+ return -EINVAL;
+ }
+
for (i = 0; i < num_objs; i++) {
row = sync_dev->sync_table + sync_obj[i];
spin_lock_bh(&sync_dev->row_spinlocks[sync_obj[i]]);
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
index 6233b46..30fda07 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
@@ -25,6 +25,7 @@
#include <linux/msm-bus-board.h>
#include <linux/regulator/consumer.h>
#include <linux/dma-direction.h>
+#include <linux/sde_rsc.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/secure_buffer.h>
#include <asm/cacheflush.h>
@@ -318,8 +319,13 @@
if (mgr->ops_hw_pre_pmevent)
mgr->ops_hw_pre_pmevent(mgr, on);
- ret = sde_rot_enable_vreg(mgr->module_power.vreg_config,
- mgr->module_power.num_vreg, on);
+ if (mgr->rsc_client)
+ ret = sde_rsc_client_state_update(mgr->rsc_client,
+ on ? SDE_RSC_CLK_STATE : SDE_RSC_IDLE_STATE,
+ NULL, -1);
+ else
+ ret = sde_rot_enable_vreg(mgr->module_power.vreg_config,
+ mgr->module_power.num_vreg, on);
if (ret) {
SDEROT_WARN("Rotator regulator failed to %s\n",
on ? "enable" : "disable");
@@ -2780,9 +2786,21 @@
{
int ret;
- ret = sde_rotator_get_dt_vreg_data(&pdev->dev, &mgr->module_power);
- if (ret)
+ mgr->rsc_client = sde_rsc_client_create(
+ SDE_RSC_INDEX, "sde_rotator_core", false);
+ if (IS_ERR(mgr->rsc_client)) {
+ ret = PTR_ERR(mgr->rsc_client);
+ pr_err("rsc client create returned %d\n", ret);
+ mgr->rsc_client = NULL;
return ret;
+ }
+
+ if (!mgr->rsc_client) {
+ ret = sde_rotator_get_dt_vreg_data(
+ &pdev->dev, &mgr->module_power);
+ if (ret)
+ return ret;
+ }
ret = sde_rotator_register_clk(pdev, mgr);
if (ret)
@@ -2802,9 +2820,15 @@
{
struct platform_device *pdev = mgr->pdev;
- sde_rotator_put_dt_vreg_data(&pdev->dev, &mgr->module_power);
sde_rotator_unregister_clk(mgr);
sde_rotator_bus_scale_unregister(mgr);
+
+ if (mgr->rsc_client) {
+ sde_rsc_client_destroy(mgr->rsc_client);
+ mgr->rsc_client = NULL;
+ } else {
+ sde_rotator_put_dt_vreg_data(&pdev->dev, &mgr->module_power);
+ }
}
int sde_rotator_core_init(struct sde_rot_mgr **pmgr,
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
index 13e7739..0051e96 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
@@ -373,6 +373,7 @@
* @reg_bus: register bus configuration state
* @module_power: power/clock configuration state
* @regulator_enable: true if foot switch is enabled; false otherwise
+ * @rsc_client: pointer to rsc client handle
* @res_ref_cnt: reference count of how many times resource is requested
* @rot_enable_clk_cnt: reference count of how many times clock is requested
* @rot_clk: array of rotator and periphery clocks
@@ -417,6 +418,8 @@
struct sde_module_power module_power;
bool regulator_enable;
+ struct sde_rsc_client *rsc_client;
+
int res_ref_cnt;
int rot_enable_clk_cnt;
struct sde_rot_clk *rot_clk;
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 2afa1eb..f37d64c 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -45,27 +45,36 @@
compat_caddr_t bitmap;
};
-static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
+static int get_v4l2_window32(struct v4l2_window __user *kp,
+ struct v4l2_window32 __user *up)
{
+ u32 clipcount = 0;
+
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
- copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
- get_user(kp->field, &up->field) ||
- get_user(kp->chromakey, &up->chromakey) ||
- get_user(kp->clipcount, &up->clipcount))
+ !access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_window)) ||
+ copy_in_user(&kp->w, &up->w, sizeof(up->w)) ||
+ copy_in_user(&kp->field, &up->field, sizeof(up->field)) ||
+ copy_in_user(&kp->chromakey, &up->chromakey,
+ sizeof(up->chromakey)) ||
+ copy_in_user(&kp->clipcount, &up->clipcount,
+ sizeof(up->clipcount)))
return -EFAULT;
- if (kp->clipcount > 2048)
+ if (get_user(clipcount, &kp->clipcount))
+ return -EFAULT;
+ if (clipcount > 2048)
return -EINVAL;
- if (kp->clipcount) {
+ if (clipcount) {
struct v4l2_clip32 __user *uclips;
struct v4l2_clip __user *kclips;
- int n = kp->clipcount;
+ int n = clipcount;
compat_caddr_t p;
if (get_user(p, &up->clips))
return -EFAULT;
uclips = compat_ptr(p);
kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
- kp->clips = kclips;
+ if (put_user(kclips, &kp->clips))
+ return -EFAULT;
while (--n >= 0) {
if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
return -EFAULT;
@@ -74,89 +83,106 @@
uclips += 1;
kclips += 1;
}
- } else
- kp->clips = NULL;
- return 0;
-}
-
-static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
-{
- if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) ||
- put_user(kp->field, &up->field) ||
- put_user(kp->chromakey, &up->chromakey) ||
- put_user(kp->clipcount, &up->clipcount))
+ } else {
+ if (put_user(NULL, &kp->clips))
return -EFAULT;
+ }
return 0;
}
-static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
+static int put_v4l2_window32(struct v4l2_window __user *kp,
+ struct v4l2_window32 __user *up)
{
- if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
+ if (copy_in_user(&up->w, &kp->w, sizeof(up->w)) ||
+ copy_in_user(&up->field, &kp->field, sizeof(up->field)) ||
+ copy_in_user(&up->chromakey, &kp->chromakey,
+ sizeof(up->chromakey)) ||
+ copy_in_user(&up->clipcount, &kp->clipcount,
+ sizeof(up->clipcount)))
return -EFAULT;
return 0;
}
-static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
+static inline int get_v4l2_pix_format(struct v4l2_pix_format __user *kp,
+ struct v4l2_pix_format __user *up)
+{
+ if (copy_in_user(kp, up, sizeof(struct v4l2_pix_format)))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int get_v4l2_pix_format_mplane(
+ struct v4l2_pix_format_mplane __user *kp,
struct v4l2_pix_format_mplane __user *up)
{
- if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
+ if (copy_in_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
return -EFAULT;
return 0;
}
-static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
+static inline int put_v4l2_pix_format(struct v4l2_pix_format __user *kp,
+ struct v4l2_pix_format __user *up)
{
- if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
+ if (copy_in_user(up, kp, sizeof(struct v4l2_pix_format)))
return -EFAULT;
return 0;
}
-static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
+static inline int put_v4l2_pix_format_mplane(
+ struct v4l2_pix_format_mplane __user *kp,
struct v4l2_pix_format_mplane __user *up)
{
- if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
+ if (copy_in_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
return -EFAULT;
return 0;
}
-static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
+static inline int get_v4l2_vbi_format(struct v4l2_vbi_format __user *kp,
+ struct v4l2_vbi_format __user *up)
{
- if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
+ if (copy_in_user(kp, up, sizeof(struct v4l2_vbi_format)))
return -EFAULT;
return 0;
}
-static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
+static inline int put_v4l2_vbi_format(struct v4l2_vbi_format __user *kp,
+ struct v4l2_vbi_format __user *up)
{
- if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
+ if (copy_in_user(up, kp, sizeof(struct v4l2_vbi_format)))
return -EFAULT;
return 0;
}
-static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up)
+static inline int get_v4l2_sliced_vbi_format(
+ struct v4l2_sliced_vbi_format __user *kp,
+ struct v4l2_sliced_vbi_format __user *up)
{
- if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
+ if (copy_in_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
return -EFAULT;
return 0;
}
-static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up)
+static inline int put_v4l2_sliced_vbi_format(
+ struct v4l2_sliced_vbi_format __user *kp,
+ struct v4l2_sliced_vbi_format __user *up)
{
- if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
+ if (copy_in_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
return -EFAULT;
return 0;
}
-static inline int get_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sdr_format __user *up)
+static inline int get_v4l2_sdr_format(struct v4l2_sdr_format __user *kp,
+ struct v4l2_sdr_format __user *up)
{
- if (copy_from_user(kp, up, sizeof(struct v4l2_sdr_format)))
+ if (copy_in_user(kp, up, sizeof(struct v4l2_sdr_format)))
return -EFAULT;
return 0;
}
-static inline int put_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sdr_format __user *up)
+static inline int put_v4l2_sdr_format(struct v4l2_sdr_format __user *kp,
+ struct v4l2_sdr_format __user *up)
{
- if (copy_to_user(up, kp, sizeof(struct v4l2_sdr_format)))
+ if (copy_in_user(up, kp, sizeof(struct v4l2_sdr_format)))
return -EFAULT;
return 0;
}
@@ -191,12 +217,17 @@
__u32 reserved[8];
};
-static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+static int __get_v4l2_format32(struct v4l2_format __user *kp,
+ struct v4l2_format32 __user *up)
{
- if (get_user(kp->type, &up->type))
+ u32 type;
+
+ if (copy_in_user(&kp->type, &up->type, sizeof(up->type)))
return -EFAULT;
- switch (kp->type) {
+ if (get_user(type, &kp->type))
+ return -EFAULT;
+ switch (type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
@@ -223,27 +254,39 @@
}
}
-static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+static int get_v4l2_format32(struct v4l2_format __user *kp,
+ struct v4l2_format32 __user *up)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)))
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
+ !access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_format)))
return -EFAULT;
return __get_v4l2_format32(kp, up);
}
-static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
+static int get_v4l2_create32(struct v4l2_create_buffers __user *kp,
+ struct v4l2_create_buffers32 __user *up)
{
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
- copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format)))
+ !access_ok(VERIFY_WRITE, kp,
+ sizeof(struct v4l2_create_buffers)) ||
+ copy_in_user(kp, up,
+ offsetof(struct v4l2_create_buffers32, format)))
return -EFAULT;
return __get_v4l2_format32(&kp->format, &up->format);
}
-static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+static int __put_v4l2_format32(struct v4l2_format __user *kp,
+ struct v4l2_format32 __user *up)
{
- if (put_user(kp->type, &up->type))
+ u32 type;
+
+ if (copy_in_user(&up->type, &kp->type, sizeof(up->type)))
return -EFAULT;
- switch (kp->type) {
+ if (get_user(type, &kp->type))
+ return -EFAULT;
+
+ switch (type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
@@ -270,18 +313,24 @@
}
}
-static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+static int put_v4l2_format32(struct v4l2_format __user *kp,
+ struct v4l2_format32 __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)))
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
+ !access_ok(VERIFY_READ, kp, sizeof(struct v4l2_format)))
return -EFAULT;
return __put_v4l2_format32(kp, up);
}
-static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
+static int put_v4l2_create32(struct v4l2_create_buffers __user *kp,
+ struct v4l2_create_buffers32 __user *up)
{
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
- copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) ||
- copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
+ !access_ok(VERIFY_READ, kp,
+ sizeof(struct v4l2_create_buffers)) ||
+ copy_in_user(up, kp,
+ offsetof(struct v4l2_create_buffers32, format)) ||
+ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
return -EFAULT;
return __put_v4l2_format32(&kp->format, &up->format);
}
@@ -295,24 +344,30 @@
__u32 reserved[4];
};
-static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
+static int get_v4l2_standard32(struct v4l2_standard __user *kp,
+ struct v4l2_standard32 __user *up)
{
/* other fields are not set by the user, nor used by the driver */
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
- get_user(kp->index, &up->index))
+ !access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_standard)) ||
+ copy_in_user(&kp->index, &up->index, sizeof(up->index)))
return -EFAULT;
return 0;
}
-static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
+static int put_v4l2_standard32(struct v4l2_standard __user *kp,
+ struct v4l2_standard32 __user *up)
{
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
- put_user(kp->index, &up->index) ||
- put_user(kp->id, &up->id) ||
- copy_to_user(up->name, kp->name, 24) ||
- copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
- put_user(kp->framelines, &up->framelines) ||
- copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
+ !access_ok(VERIFY_READ, kp, sizeof(struct v4l2_standard)) ||
+ copy_in_user(&up->index, &kp->index, sizeof(up->index)) ||
+ copy_in_user(&up->id, &kp->id, sizeof(up->id)) ||
+ copy_in_user(up->name, kp->name, 24) ||
+ copy_in_user(&up->frameperiod, &kp->frameperiod,
+ sizeof(up->frameperiod)) ||
+ copy_in_user(&up->framelines, &kp->framelines,
+ sizeof(up->framelines)) ||
+ copy_in_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
return -EFAULT;
return 0;
}
@@ -410,34 +465,48 @@
return 0;
}
-static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
+static int get_v4l2_buffer32(struct v4l2_buffer __user *kp,
+ struct v4l2_buffer32 __user *up)
{
struct v4l2_plane32 __user *uplane32;
struct v4l2_plane __user *uplane;
compat_caddr_t p;
int num_planes;
+ struct timeval time;
+ u32 plane_count, memory, type;
int ret;
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
- get_user(kp->index, &up->index) ||
- get_user(kp->type, &up->type) ||
- get_user(kp->flags, &up->flags) ||
- get_user(kp->memory, &up->memory) ||
- get_user(kp->length, &up->length))
+ !access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_buffer)) ||
+ copy_in_user(&kp->index, &up->index, sizeof(up->index)) ||
+ copy_in_user(&kp->type, &up->type, sizeof(up->type)) ||
+ copy_in_user(&kp->flags, &up->flags, sizeof(up->flags)) ||
+ copy_in_user(&kp->memory, &up->memory, sizeof(up->memory)) ||
+ copy_in_user(&kp->length, &up->length, sizeof(up->length)))
return -EFAULT;
- if (V4L2_TYPE_IS_OUTPUT(kp->type))
- if (get_user(kp->bytesused, &up->bytesused) ||
- get_user(kp->field, &up->field) ||
- get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
- get_user(kp->timestamp.tv_usec,
- &up->timestamp.tv_usec))
+ if (get_user(type, &kp->type))
+ return -EFAULT;
+ if (V4L2_TYPE_IS_OUTPUT(type))
+ if (copy_in_user(&kp->bytesused, &up->bytesused,
+ sizeof(up->bytesused)) ||
+ copy_in_user(&kp->field, &up->field,
+ sizeof(up->field)) ||
+ get_user(time.tv_sec, &up->timestamp.tv_sec) ||
+ get_user(time.tv_usec, &up->timestamp.tv_usec) ||
+ put_user(time.tv_sec, &kp->timestamp.tv_sec) ||
+ put_user(time.tv_usec, &kp->timestamp.tv_usec))
return -EFAULT;
- if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
- num_planes = kp->length;
+ if (get_user(memory, &kp->memory))
+ return -EFAULT;
+ if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
+ if (get_user(plane_count, &kp->length))
+ return -EFAULT;
+ num_planes = plane_count;
if (num_planes == 0) {
- kp->m.planes = NULL;
+ if (put_user(NULL, &kp->m.planes))
+ return -EFAULT;
/* num_planes == 0 is legal, e.g. when userspace doesn't
* need planes array on DQBUF*/
return 0;
@@ -455,37 +524,43 @@
* by passing a very big num_planes value */
uplane = compat_alloc_user_space(num_planes *
sizeof(struct v4l2_plane));
- kp->m.planes = (__force struct v4l2_plane *)uplane;
+ if (put_user(uplane, &kp->m.planes))
+ return -EFAULT;
while (--num_planes >= 0) {
- ret = get_v4l2_plane32(uplane, uplane32, kp->memory);
+ ret = get_v4l2_plane32(uplane, uplane32, memory);
if (ret)
return ret;
++uplane;
++uplane32;
}
} else {
- switch (kp->memory) {
+ switch (memory) {
case V4L2_MEMORY_MMAP:
- if (get_user(kp->m.offset, &up->m.offset))
+ if (copy_in_user(&kp->m.offset, &up->m.offset,
+ sizeof(up->m.offset)))
return -EFAULT;
break;
case V4L2_MEMORY_USERPTR:
{
compat_long_t tmp;
+ unsigned long userptr;
if (get_user(tmp, &up->m.userptr))
return -EFAULT;
- kp->m.userptr = (unsigned long)compat_ptr(tmp);
+ userptr = (unsigned long)compat_ptr(tmp);
+ put_user(userptr, &kp->m.userptr);
}
break;
case V4L2_MEMORY_OVERLAY:
- if (get_user(kp->m.offset, &up->m.offset))
+ if (copy_in_user(&kp->m.offset, &up->m.offset,
+ sizeof(up->m.offset)))
return -EFAULT;
break;
case V4L2_MEMORY_DMABUF:
- if (get_user(kp->m.fd, &up->m.fd))
+ if (copy_in_user(&kp->m.fd, &up->m.fd,
+ sizeof(up->m.fd)))
return -EFAULT;
break;
}
@@ -494,65 +569,86 @@
return 0;
}
-static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
+static int put_v4l2_buffer32(struct v4l2_buffer __user *kp,
+ struct v4l2_buffer32 __user *up)
{
struct v4l2_plane32 __user *uplane32;
struct v4l2_plane __user *uplane;
compat_caddr_t p;
int num_planes;
int ret;
+ struct timeval time;
+ u32 memory, type, length;
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
- put_user(kp->index, &up->index) ||
- put_user(kp->type, &up->type) ||
- put_user(kp->flags, &up->flags) ||
- put_user(kp->memory, &up->memory))
- return -EFAULT;
+ !access_ok(VERIFY_READ, kp, sizeof(struct v4l2_buffer)) ||
+ copy_in_user(&up->index, &kp->index, sizeof(up->index)) ||
+ copy_in_user(&up->type, &kp->type, sizeof(up->type)) ||
+ copy_in_user(&up->flags, &kp->flags, sizeof(up->flags)) ||
+ copy_in_user(&up->memory, &kp->memory, sizeof(up->memory)))
+ return -EFAULT;
- if (put_user(kp->bytesused, &up->bytesused) ||
- put_user(kp->field, &up->field) ||
- put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
- put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
- copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
- put_user(kp->sequence, &up->sequence) ||
- put_user(kp->reserved2, &up->reserved2) ||
- put_user(kp->reserved, &up->reserved) ||
- put_user(kp->length, &up->length))
- return -EFAULT;
+ if (copy_in_user(&up->bytesused, &kp->bytesused,
+ sizeof(up->bytesused)) ||
+ copy_in_user(&up->field, &kp->field, sizeof(up->field)) ||
+ get_user(time.tv_sec, &kp->timestamp.tv_sec) ||
+ get_user(time.tv_usec, &kp->timestamp.tv_usec) ||
+ put_user(time.tv_sec, &up->timestamp.tv_sec) ||
+ put_user(time.tv_usec, &up->timestamp.tv_usec) ||
+ copy_in_user(&up->timecode, &kp->timecode,
+ sizeof(struct v4l2_timecode)) ||
+ copy_in_user(&up->sequence, &kp->sequence,
+ sizeof(up->sequence)) ||
+ copy_in_user(&up->reserved2, &kp->reserved2,
+ sizeof(up->reserved2)) ||
+ copy_in_user(&up->reserved, &kp->reserved,
+ sizeof(up->reserved)) ||
+ copy_in_user(&up->length, &kp->length, sizeof(up->length)))
+ return -EFAULT;
- if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
- num_planes = kp->length;
+ if (get_user(type, &kp->type) ||
+ get_user(memory, &kp->memory) ||
+ get_user(length, &kp->length))
+ return -EINVAL;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
+ num_planes = length;
if (num_planes == 0)
return 0;
- uplane = (__force struct v4l2_plane __user *)kp->m.planes;
+ if (get_user(uplane, &kp->m.planes))
+ return -EFAULT;
if (get_user(p, &up->m.planes))
return -EFAULT;
uplane32 = compat_ptr(p);
while (--num_planes >= 0) {
- ret = put_v4l2_plane32(uplane, uplane32, kp->memory);
+ ret = put_v4l2_plane32(uplane, uplane32, memory);
if (ret)
return ret;
++uplane;
++uplane32;
}
} else {
- switch (kp->memory) {
+ switch (memory) {
case V4L2_MEMORY_MMAP:
- if (put_user(kp->m.offset, &up->m.offset))
+ if (copy_in_user(&up->m.offset, &kp->m.offset,
+ sizeof(up->m.offset)))
return -EFAULT;
break;
case V4L2_MEMORY_USERPTR:
- if (put_user(kp->m.userptr, &up->m.userptr))
+ if (copy_in_user(&up->m.userptr, &kp->m.userptr,
+ sizeof(up->m.userptr)))
return -EFAULT;
break;
case V4L2_MEMORY_OVERLAY:
- if (put_user(kp->m.offset, &up->m.offset))
+ if (copy_in_user(&up->m.offset, &kp->m.offset,
+ sizeof(up->m.offset)))
return -EFAULT;
break;
case V4L2_MEMORY_DMABUF:
- if (put_user(kp->m.fd, &up->m.fd))
+ if (copy_in_user(&up->m.fd, &kp->m.fd,
+ sizeof(up->m.fd)))
return -EFAULT;
break;
}
@@ -577,29 +673,39 @@
} fmt;
};
-static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
+static int get_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
+ struct v4l2_framebuffer32 __user *up)
{
u32 tmp;
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
+ !access_ok(VERIFY_WRITE, kp,
+ sizeof(struct v4l2_framebuffer)) ||
get_user(tmp, &up->base) ||
- get_user(kp->capability, &up->capability) ||
- get_user(kp->flags, &up->flags) ||
- copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt)))
+ put_user(compat_ptr(tmp), &kp->base) ||
+ copy_in_user(&kp->capability, &up->capability,
+ sizeof(up->capability)) ||
+ copy_in_user(&kp->flags, &up->flags, sizeof(up->flags)) ||
+ copy_in_user(&kp->fmt, &up->fmt, sizeof(up->fmt)))
return -EFAULT;
- kp->base = (__force void *)compat_ptr(tmp);
+
return 0;
}
-static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
+static int put_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
+ struct v4l2_framebuffer32 __user *up)
{
- u32 tmp = (u32)((unsigned long)kp->base);
+ unsigned long base;
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
- put_user(tmp, &up->base) ||
- put_user(kp->capability, &up->capability) ||
- put_user(kp->flags, &up->flags) ||
- copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt)))
+ !access_ok(VERIFY_READ, kp,
+ sizeof(struct v4l2_framebuffer)) ||
+ copy_from_user(&base, &kp->base, sizeof(base)) ||
+ put_user((u32)base, &up->base) ||
+ copy_in_user(&up->capability, &kp->capability,
+ sizeof(up->capability)) ||
+ copy_in_user(&up->flags, &kp->flags, sizeof(up->flags)) ||
+ copy_in_user(&up->fmt, &kp->fmt, sizeof(up->fmt)))
return -EFAULT;
return 0;
}
@@ -617,16 +723,18 @@
/* The 64-bit v4l2_input struct has extra padding at the end of the struct.
Otherwise it is identical to the 32-bit version. */
-static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
+static inline int get_v4l2_input32(struct v4l2_input __user *kp,
+ struct v4l2_input32 __user *up)
{
- if (copy_from_user(kp, up, sizeof(struct v4l2_input32)))
+ if (copy_in_user(kp, up, sizeof(struct v4l2_input32)))
return -EFAULT;
return 0;
}
-static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
+static inline int put_v4l2_input32(struct v4l2_input __user *kp,
+ struct v4l2_input32 __user *up)
{
- if (copy_to_user(up, kp, sizeof(struct v4l2_input32)))
+ if (copy_in_user(up, kp, sizeof(struct v4l2_input32)))
return -EFAULT;
return 0;
}
@@ -667,23 +775,33 @@
}
}
-static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
+static int get_v4l2_ext_controls32(struct v4l2_ext_controls __user *kp,
+ struct v4l2_ext_controls32 __user *up)
{
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols;
int n;
compat_caddr_t p;
+ u32 count;
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) ||
- get_user(kp->which, &up->which) ||
- get_user(kp->count, &up->count) ||
- get_user(kp->error_idx, &up->error_idx) ||
- copy_from_user(kp->reserved, up->reserved,
- sizeof(kp->reserved)))
+ !access_ok(VERIFY_WRITE, kp,
+ sizeof(struct v4l2_ext_controls)) ||
+ copy_in_user(&kp->which, &up->which,
+ sizeof(up->which)) ||
+ copy_in_user(&kp->count, &up->count, sizeof(up->count)) ||
+ copy_in_user(&kp->error_idx, &up->error_idx,
+ sizeof(up->error_idx)) ||
+ copy_in_user(kp->reserved, up->reserved,
+ sizeof(up->reserved)))
return -EFAULT;
- n = kp->count;
+
+ if (get_user(count, &kp->count))
+ return -EFAULT;
+ n = count;
if (n == 0) {
- kp->controls = NULL;
+ if (put_user(NULL, &kp->controls))
+ return -EINVAL;
return 0;
}
if (get_user(p, &up->controls))
@@ -693,7 +811,9 @@
n * sizeof(struct v4l2_ext_control32)))
return -EFAULT;
kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
- kp->controls = (__force struct v4l2_ext_control *)kcontrols;
+ if (put_user(kcontrols, &kp->controls))
+ return -EFAULT;
+
while (--n >= 0) {
u32 id;
@@ -716,23 +836,33 @@
return 0;
}
-static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
+static int put_v4l2_ext_controls32(struct v4l2_ext_controls __user *kp,
+ struct v4l2_ext_controls32 __user *up)
{
struct v4l2_ext_control32 __user *ucontrols;
- struct v4l2_ext_control __user *kcontrols =
- (__force struct v4l2_ext_control __user *)kp->controls;
- int n = kp->count;
+ struct v4l2_ext_control __user *kcontrols;
+ int n;
+ u32 count;
compat_caddr_t p;
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) ||
- put_user(kp->which, &up->which) ||
- put_user(kp->count, &up->count) ||
- put_user(kp->error_idx, &up->error_idx) ||
- copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+ !access_ok(VERIFY_READ, kp,
+ sizeof(struct v4l2_ext_controls)) ||
+ copy_in_user(&up->which, &kp->which,
+ sizeof(up->which)) ||
+ copy_in_user(&up->count, &kp->count,
+ sizeof(up->count)) ||
+ copy_in_user(&up->error_idx, &kp->error_idx,
+ sizeof(up->error_idx)) ||
+ copy_in_user(up->reserved, kp->reserved,
+ sizeof(up->reserved)) ||
+ get_user(count, &kp->count) ||
+ get_user(kcontrols, &kp->controls))
return -EFAULT;
- if (!kp->count)
+ if (!count)
return 0;
+ n = count;
if (get_user(p, &up->controls))
return -EFAULT;
ucontrols = compat_ptr(p);
@@ -772,16 +902,22 @@
__u32 reserved[8];
};
-static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up)
+static int put_v4l2_event32(struct v4l2_event __user *kp,
+ struct v4l2_event32 __user *up)
{
+ struct timespec ts;
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) ||
- put_user(kp->type, &up->type) ||
- copy_to_user(&up->u, &kp->u, sizeof(kp->u)) ||
- put_user(kp->pending, &up->pending) ||
- put_user(kp->sequence, &up->sequence) ||
- compat_put_timespec(&kp->timestamp, &up->timestamp) ||
- put_user(kp->id, &up->id) ||
- copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
+ !access_ok(VERIFY_READ, kp, sizeof(struct v4l2_event)) ||
+ copy_in_user(&up->type, &kp->type, sizeof(up->type)) ||
+ copy_in_user(&up->u, &kp->u, sizeof(up->u)) ||
+ copy_in_user(&up->pending, &kp->pending,
+ sizeof(up->pending)) ||
+ copy_in_user(&up->sequence, &kp->sequence,
+ sizeof(up->sequence)) ||
+ copy_from_user(&ts, &kp->timestamp, sizeof(ts)) ||
+ compat_put_timespec(&ts, &up->timestamp) ||
+ copy_in_user(&up->id, &kp->id, sizeof(up->id)) ||
+ copy_in_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
return -EFAULT;
return 0;
}
@@ -794,31 +930,39 @@
compat_caddr_t edid;
};
-static int get_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up)
+static int get_v4l2_edid32(struct v4l2_edid __user *kp,
+ struct v4l2_edid32 __user *up)
{
u32 tmp;
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_edid32)) ||
- get_user(kp->pad, &up->pad) ||
- get_user(kp->start_block, &up->start_block) ||
- get_user(kp->blocks, &up->blocks) ||
+ !access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_edid)) ||
+ copy_in_user(&kp->pad, &up->pad, sizeof(up->pad)) ||
+ copy_in_user(&kp->start_block, &up->start_block,
+ sizeof(up->start_block)) ||
+ copy_in_user(&kp->blocks, &up->blocks, sizeof(up->blocks)) ||
get_user(tmp, &up->edid) ||
- copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
+ put_user(compat_ptr(tmp), &kp->edid) ||
+ copy_in_user(kp->reserved, up->reserved,
+ sizeof(kp->reserved)))
return -EFAULT;
- kp->edid = (__force u8 *)compat_ptr(tmp);
return 0;
}
-static int put_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up)
+static int put_v4l2_edid32(struct v4l2_edid __user *kp,
+ struct v4l2_edid32 __user *up)
{
- u32 tmp = (u32)((unsigned long)kp->edid);
+ unsigned long ptr;
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_edid32)) ||
- put_user(kp->pad, &up->pad) ||
- put_user(kp->start_block, &up->start_block) ||
- put_user(kp->blocks, &up->blocks) ||
- put_user(tmp, &up->edid) ||
- copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+ !access_ok(VERIFY_READ, kp, sizeof(struct v4l2_edid)) ||
+ copy_in_user(&up->pad, &kp->pad, sizeof(up->pad)) ||
+ copy_in_user(&up->start_block, &kp->start_block,
+ sizeof(up->start_block)) ||
+ copy_in_user(&up->blocks, &kp->blocks, sizeof(up->blocks)) ||
+ copy_from_user(&ptr, &kp->edid, sizeof(ptr)) ||
+ put_user((u32)ptr, &up->edid) ||
+ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
return -EFAULT;
return 0;
}
@@ -865,11 +1009,16 @@
struct v4l2_edid v2edid;
unsigned long vx;
int vi;
- } karg;
+ } *karg;
void __user *up = compat_ptr(arg);
int compatible_arg = 1;
long err = 0;
+ karg = compat_alloc_user_space(sizeof(*karg));
+ if (karg == NULL) {
+ return -EFAULT;
+ }
+
/* First, convert the command. */
switch (cmd) {
case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
@@ -905,7 +1054,8 @@
case VIDIOC_STREAMOFF:
case VIDIOC_S_INPUT:
case VIDIOC_S_OUTPUT:
- err = get_user(karg.vi, (s32 __user *)up);
+ err = copy_in_user(&karg->vi, (s32 __user *)up,
+ sizeof(karg->vi));
compatible_arg = 0;
break;
@@ -916,19 +1066,19 @@
case VIDIOC_G_EDID:
case VIDIOC_S_EDID:
- err = get_v4l2_edid32(&karg.v2edid, up);
+ err = get_v4l2_edid32(&karg->v2edid, up);
compatible_arg = 0;
break;
case VIDIOC_G_FMT:
case VIDIOC_S_FMT:
case VIDIOC_TRY_FMT:
- err = get_v4l2_format32(&karg.v2f, up);
+ err = get_v4l2_format32(&karg->v2f, up);
compatible_arg = 0;
break;
case VIDIOC_CREATE_BUFS:
- err = get_v4l2_create32(&karg.v2crt, up);
+ err = get_v4l2_create32(&karg->v2crt, up);
compatible_arg = 0;
break;
@@ -936,12 +1086,12 @@
case VIDIOC_QUERYBUF:
case VIDIOC_QBUF:
case VIDIOC_DQBUF:
- err = get_v4l2_buffer32(&karg.v2b, up);
+ err = get_v4l2_buffer32(&karg->v2b, up);
compatible_arg = 0;
break;
case VIDIOC_S_FBUF:
- err = get_v4l2_framebuffer32(&karg.v2fb, up);
+ err = get_v4l2_framebuffer32(&karg->v2fb, up);
compatible_arg = 0;
break;
@@ -950,19 +1100,19 @@
break;
case VIDIOC_ENUMSTD:
- err = get_v4l2_standard32(&karg.v2s, up);
+ err = get_v4l2_standard32(&karg->v2s, up);
compatible_arg = 0;
break;
case VIDIOC_ENUMINPUT:
- err = get_v4l2_input32(&karg.v2i, up);
+ err = get_v4l2_input32(&karg->v2i, up);
compatible_arg = 0;
break;
case VIDIOC_G_EXT_CTRLS:
case VIDIOC_S_EXT_CTRLS:
case VIDIOC_TRY_EXT_CTRLS:
- err = get_v4l2_ext_controls32(&karg.v2ecs, up);
+ err = get_v4l2_ext_controls32(&karg->v2ecs, up);
compatible_arg = 0;
break;
case VIDIOC_DQEVENT:
@@ -975,11 +1125,7 @@
if (compatible_arg)
err = native_ioctl(file, cmd, (unsigned long)up);
else {
- mm_segment_t old_fs = get_fs();
-
- set_fs(KERNEL_DS);
- err = native_ioctl(file, cmd, (unsigned long)&karg);
- set_fs(old_fs);
+ err = native_ioctl(file, cmd, (unsigned long)karg);
}
/* Special case: even after an error we need to put the
@@ -989,7 +1135,7 @@
case VIDIOC_G_EXT_CTRLS:
case VIDIOC_S_EXT_CTRLS:
case VIDIOC_TRY_EXT_CTRLS:
- if (put_v4l2_ext_controls32(&karg.v2ecs, up))
+ if (put_v4l2_ext_controls32(&karg->v2ecs, up))
err = -EFAULT;
break;
}
@@ -1001,44 +1147,44 @@
case VIDIOC_S_OUTPUT:
case VIDIOC_G_INPUT:
case VIDIOC_G_OUTPUT:
- err = put_user(((s32)karg.vi), (s32 __user *)up);
+ err = copy_in_user(up, &karg->vi, sizeof(s32));
break;
case VIDIOC_G_FBUF:
- err = put_v4l2_framebuffer32(&karg.v2fb, up);
+ err = put_v4l2_framebuffer32(&karg->v2fb, up);
break;
case VIDIOC_DQEVENT:
- err = put_v4l2_event32(&karg.v2ev, up);
+ err = put_v4l2_event32(&karg->v2ev, up);
break;
case VIDIOC_G_EDID:
case VIDIOC_S_EDID:
- err = put_v4l2_edid32(&karg.v2edid, up);
+ err = put_v4l2_edid32(&karg->v2edid, up);
break;
case VIDIOC_G_FMT:
case VIDIOC_S_FMT:
case VIDIOC_TRY_FMT:
- err = put_v4l2_format32(&karg.v2f, up);
+ err = put_v4l2_format32(&karg->v2f, up);
break;
case VIDIOC_CREATE_BUFS:
- err = put_v4l2_create32(&karg.v2crt, up);
+ err = put_v4l2_create32(&karg->v2crt, up);
break;
case VIDIOC_QUERYBUF:
case VIDIOC_QBUF:
case VIDIOC_DQBUF:
- err = put_v4l2_buffer32(&karg.v2b, up);
+ err = put_v4l2_buffer32(&karg->v2b, up);
break;
case VIDIOC_ENUMSTD:
- err = put_v4l2_standard32(&karg.v2s, up);
+ err = put_v4l2_standard32(&karg->v2s, up);
break;
case VIDIOC_ENUMINPUT:
- err = put_v4l2_input32(&karg.v2i, up);
+ err = put_v4l2_input32(&karg->v2i, up);
break;
}
return err;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index af4d4c8..fb42ef7 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c
@@ -3679,6 +3679,7 @@
* pipe will be unsuspended as part of
* enabling IPA clocks
*/
+ mutex_lock(&ipa_ctx->sps_pm.sps_pm_lock);
if (!atomic_read(
&ipa_ctx->sps_pm.dec_clients)
) {
@@ -3691,6 +3692,7 @@
1);
ipa_sps_process_irq_schedule_rel();
}
+ mutex_unlock(&ipa_ctx->sps_pm.sps_pm_lock);
} else {
resource = ipa2_get_rm_resource_from_ep(i);
res = ipa_rm_request_resource_with_timer(
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 83fd2b2..30f5712 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -3620,6 +3620,8 @@
* pipe will be unsuspended as part of
* enabling IPA clocks
*/
+ mutex_lock(&ipa3_ctx->transport_pm.
+ transport_pm_mutex);
if (!atomic_read(
&ipa3_ctx->transport_pm.dec_clients)
) {
@@ -3632,6 +3634,8 @@
1);
ipa3_process_irq_schedule_rel();
}
+ mutex_unlock(&ipa3_ctx->transport_pm.
+ transport_pm_mutex);
} else {
resource = ipa3_get_rm_resource_from_ep(i);
res =
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 69e3032..3311380 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -655,3 +655,11 @@
memory location. These messages provide statistical information about
the low power modes that RPM enters. The drivers outputs the message
via a debugfs node.
+
+config QCOM_FORCE_WDOG_BITE_ON_PANIC
+ bool "QCOM force watchdog bite"
+ depends on QCOM_WATCHDOG_V2
+ help
+ This forces a watchdog bite when the device restarts due to a
+ kernel panic. On certain MSM SoCs, this provides us
+ additional debugging information.
diff --git a/drivers/soc/qcom/glink_private.h b/drivers/soc/qcom/glink_private.h
index c837bd8..9810207 100644
--- a/drivers/soc/qcom/glink_private.h
+++ b/drivers/soc/qcom/glink_private.h
@@ -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
@@ -700,6 +700,7 @@
* edge: The G-Link edge name for the channel associated with
* this callback data
* do_cleanup_data: Structure containing the G-Link SSR do_cleanup message.
+ * cb_kref: Kref object to maintain cb_data reference.
*/
struct ssr_notify_data {
bool tx_done;
@@ -707,6 +708,7 @@
bool responded;
const char *edge;
struct do_cleanup_msg *do_cleanup_data;
+ struct kref cb_kref;
};
/**
@@ -741,6 +743,7 @@
int notify_list_len;
bool link_up;
spinlock_t link_up_lock;
+ spinlock_t cb_lock;
};
/**
diff --git a/drivers/soc/qcom/glink_ssr.c b/drivers/soc/qcom/glink_ssr.c
index b24598a..4737288 100644
--- a/drivers/soc/qcom/glink_ssr.c
+++ b/drivers/soc/qcom/glink_ssr.c
@@ -115,6 +115,44 @@
static atomic_t responses_remaining = ATOMIC_INIT(0);
static wait_queue_head_t waitqueue;
+/**
+ * cb_data_release() - Free cb_data and set to NULL
+ * @kref_ptr: pointer to kref.
+ *
+ * This function releses cb_data.
+ */
+static inline void cb_data_release(struct kref *kref_ptr)
+{
+ struct ssr_notify_data *cb_data;
+
+ cb_data = container_of(kref_ptr, struct ssr_notify_data, cb_kref);
+ kfree(cb_data);
+}
+
+/**
+ * check_and_get_cb_data() - Try to get reference to kref of cb_data
+ * @ss_info: pointer to subsystem info structure.
+ *
+ * Return: NULL is cb_data is NULL, pointer to cb_data otherwise
+ */
+static struct ssr_notify_data *check_and_get_cb_data(
+ struct subsys_info *ss_info)
+{
+ struct ssr_notify_data *cb_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ss_info->cb_lock, flags);
+ if (ss_info->cb_data == NULL) {
+ GLINK_SSR_LOG("<SSR> %s: cb_data is NULL\n", __func__);
+ spin_unlock_irqrestore(&ss_info->cb_lock, flags);
+ return 0;
+ }
+ kref_get(&ss_info->cb_data->cb_kref);
+ cb_data = ss_info->cb_data;
+ spin_unlock_irqrestore(&ss_info->cb_lock, flags);
+ return cb_data;
+}
+
static void rx_done_cb_worker(struct work_struct *work)
{
struct rx_done_ch_work *rx_done_work =
@@ -340,8 +378,10 @@
if (WARN_ON(!ss_info->cb_data))
return;
- kfree(ss_info->cb_data);
+ spin_lock_irqsave(&ss_info->cb_lock, flags);
+ kref_put(&ss_info->cb_data->cb_kref, cb_data_release);
ss_info->cb_data = NULL;
+ spin_unlock_irqrestore(&ss_info->cb_lock, flags);
kfree(close_work);
}
@@ -508,13 +548,18 @@
return -ENODEV;
}
handle = ss_info_channel->handle;
- ss_leaf_entry->cb_data = ss_info_channel->cb_data;
+ ss_leaf_entry->cb_data = check_and_get_cb_data(
+ ss_info_channel);
+ if (!ss_leaf_entry->cb_data) {
+ GLINK_SSR_LOG("<SSR> %s: CB data is NULL\n", __func__);
+ atomic_dec(&responses_remaining);
+ continue;
+ }
spin_lock_irqsave(&ss_info->link_up_lock, flags);
if (IS_ERR_OR_NULL(ss_info_channel->handle) ||
- !ss_info_channel->cb_data ||
!ss_info_channel->link_up ||
- ss_info_channel->cb_data->event
+ ss_leaf_entry->cb_data->event
!= GLINK_CONNECTED) {
GLINK_SSR_LOG(
@@ -527,6 +572,8 @@
spin_unlock_irqrestore(&ss_info->link_up_lock, flags);
atomic_dec(&responses_remaining);
+ kref_put(&ss_leaf_entry->cb_data->cb_kref,
+ cb_data_release);
continue;
}
spin_unlock_irqrestore(&ss_info->link_up_lock, flags);
@@ -537,6 +584,8 @@
GLINK_SSR_ERR(
"%s %s: Could not allocate do_cleanup_msg\n",
"<SSR>", __func__);
+ kref_put(&ss_leaf_entry->cb_data->cb_kref,
+ cb_data_release);
return -ENOMEM;
}
@@ -568,6 +617,8 @@
__func__);
}
atomic_dec(&responses_remaining);
+ kref_put(&ss_leaf_entry->cb_data->cb_kref,
+ cb_data_release);
continue;
}
@@ -597,10 +648,12 @@
__func__);
}
atomic_dec(&responses_remaining);
+ kref_put(&ss_leaf_entry->cb_data->cb_kref,
+ cb_data_release);
continue;
}
-
sequence_number++;
+ kref_put(&ss_leaf_entry->cb_data->cb_kref, cb_data_release);
}
wait_ret = wait_event_timeout(waitqueue,
@@ -609,6 +662,21 @@
list_for_each_entry(ss_leaf_entry, &ss_info->notify_list,
notify_list_node) {
+ ss_info_channel =
+ get_info_for_subsystem(ss_leaf_entry->ssr_name);
+ if (ss_info_channel == NULL) {
+ GLINK_SSR_ERR(
+ "<SSR> %s: unable to find subsystem name\n",
+ __func__);
+ continue;
+ }
+
+ ss_leaf_entry->cb_data = check_and_get_cb_data(
+ ss_info_channel);
+ if (!ss_leaf_entry->cb_data) {
+ GLINK_SSR_LOG("<SSR> %s: CB data is NULL\n", __func__);
+ continue;
+ }
if (!wait_ret && !IS_ERR_OR_NULL(ss_leaf_entry->cb_data)
&& !ss_leaf_entry->cb_data->responded) {
GLINK_SSR_ERR("%s %s: Subsystem %s %s\n",
@@ -627,6 +695,7 @@
if (!IS_ERR_OR_NULL(ss_leaf_entry->cb_data))
ss_leaf_entry->cb_data->responded = false;
+ kref_put(&ss_leaf_entry->cb_data->cb_kref, cb_data_release);
}
complete(¬ifications_successful_complete);
return 0;
@@ -645,6 +714,7 @@
struct glink_open_config open_cfg;
struct ssr_notify_data *cb_data = NULL;
void *handle = NULL;
+ unsigned long flags;
if (!ss_info) {
GLINK_SSR_ERR("<SSR> %s: ss_info structure invalid\n",
@@ -661,7 +731,10 @@
cb_data->responded = false;
cb_data->event = GLINK_SSR_EVENT_INIT;
cb_data->edge = ss_info->edge;
+ spin_lock_irqsave(&ss_info->cb_lock, flags);
ss_info->cb_data = cb_data;
+ kref_init(&cb_data->cb_kref);
+ spin_unlock_irqrestore(&ss_info->cb_lock, flags);
memset(&open_cfg, 0, sizeof(struct glink_open_config));
@@ -877,6 +950,7 @@
ss_info->link_state_handle = NULL;
ss_info->cb_data = NULL;
spin_lock_init(&ss_info->link_up_lock);
+ spin_lock_init(&ss_info->cb_lock);
nb = kmalloc(sizeof(struct restart_notifier_block), GFP_KERNEL);
if (!nb) {
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index df9be34..da1a0e6 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -94,8 +94,10 @@
#define UART_OVERSAMPLING (32)
#define STALE_TIMEOUT (16)
+#define DEFAULT_BITS_PER_CHAR (10)
#define GENI_UART_NR_PORTS (15)
#define DEF_FIFO_DEPTH_WORDS (16)
+#define DEF_TX_WM (2)
#define DEF_FIFO_WIDTH_BITS (32)
#define UART_CORE2X_VOTE (10000)
#define DEFAULT_SE_CLK (19200000)
@@ -134,6 +136,7 @@
unsigned int rx_fifo_wc,
unsigned int rx_last_byte_valid,
unsigned int rx_last);
+static unsigned int msm_geni_serial_tx_empty(struct uart_port *port);
static atomic_t uart_line_id = ATOMIC_INIT(0);
@@ -232,7 +235,7 @@
}
static void msm_geni_serial_setup_tx(struct uart_port *uport,
- unsigned int xmit_size)
+ unsigned int xmit_size)
{
u32 m_cmd = 0;
@@ -324,7 +327,6 @@
int b = (int) c;
struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
- se_config_packing(uport->membase, 8, 1, false);
geni_write_reg_nolog(port->tx_wm, uport->membase,
SE_GENI_TX_WATERMARK_REG);
msm_geni_serial_setup_tx(uport, 1);
@@ -358,10 +360,11 @@
__msm_geni_serial_console_write(struct uart_port *uport, const char *s,
unsigned int count)
{
- struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
int new_line = 0;
int i;
int bytes_to_send = count;
+ int fifo_depth = DEF_FIFO_DEPTH_WORDS;
+ int tx_wm = DEF_TX_WM;
for (i = 0; i < count; i++) {
if (s[i] == '\n')
@@ -369,14 +372,13 @@
}
bytes_to_send += new_line;
- se_config_packing(uport->membase, 8, 1, false);
- geni_write_reg_nolog(port->tx_wm, uport->membase,
+ geni_write_reg_nolog(tx_wm, uport->membase,
SE_GENI_TX_WATERMARK_REG);
msm_geni_serial_setup_tx(uport, bytes_to_send);
i = 0;
while (i < count) {
u32 chars_to_write = 0;
- u32 avail_fifo_bytes = (port->tx_fifo_depth - port->tx_wm);
+ u32 avail_fifo_bytes = (fifo_depth - tx_wm);
/*
* If the WM bit never set, then the Tx state machine is not
* in a valid state, so break, cancel/abort any existing
@@ -473,10 +475,12 @@
unsigned int geni_m_irq_en;
struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
+ if (!msm_geni_serial_tx_empty(uport))
+ return;
+
geni_m_irq_en = geni_read_reg_nolog(uport->membase, SE_GENI_M_IRQ_EN);
geni_m_irq_en |= M_TX_FIFO_WATERMARK_EN;
- se_config_packing(uport->membase, 8, 4, false);
geni_write_reg_nolog(port->tx_wm, uport->membase,
SE_GENI_TX_WATERMARK_REG);
geni_write_reg_nolog(geni_m_irq_en, uport->membase, SE_GENI_M_IRQ_EN);
@@ -516,6 +520,8 @@
{
unsigned int geni_s_irq_en;
unsigned int geni_m_irq_en;
+ unsigned long cfg0, cfg1;
+ unsigned int rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT;
msm_geni_serial_abort_rx(uport);
geni_s_irq_en = geni_read_reg_nolog(uport->membase,
@@ -524,7 +530,10 @@
SE_GENI_M_IRQ_EN);
geni_s_irq_en |= S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN;
geni_m_irq_en |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN;
-
+ se_get_packing_config(8, 4, false, &cfg0, &cfg1);
+ geni_write_reg_nolog(cfg0, uport->membase, SE_GENI_RX_PACKING_CFG0);
+ geni_write_reg_nolog(cfg1, uport->membase, SE_GENI_RX_PACKING_CFG1);
+ geni_write_reg_nolog(rxstale, uport->membase, SE_UART_RX_STALE_CNT);
geni_setup_s_cmd(uport->membase, UART_START_READ, 0);
geni_write_reg_nolog(geni_s_irq_en, uport->membase, SE_GENI_S_IRQ_EN);
geni_write_reg_nolog(geni_m_irq_en, uport->membase, SE_GENI_M_IRQ_EN);
@@ -622,7 +631,8 @@
int i = 0;
unsigned int tx_fifo_status;
unsigned int xmit_size;
- unsigned int fifo_width_bytes = msm_port->tx_fifo_width >> 3;
+ unsigned int fifo_width_bytes =
+ (uart_console(uport) ? 1 : (msm_port->tx_fifo_width >> 3));
tx_fifo_status = geni_read_reg_nolog(uport->membase,
SE_GENI_TX_FIFO_STATUS);
@@ -664,6 +674,8 @@
wmb();
}
msm_geni_serial_poll_cancel_tx(uport);
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(uport);
exit_handle_tx:
return ret;
}
@@ -765,17 +777,32 @@
{
int ret = 0;
struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
+ unsigned long cfg0, cfg1;
- /* For now only assume FIFO mode. */
- msm_port->xfer_mode = FIFO_MODE;
- set_rfr_wm(msm_port);
- ret = geni_se_init(uport->membase, msm_port->xfer_mode,
+
+ if (!uart_console(uport)) {
+ /* For now only assume FIFO mode. */
+ msm_port->xfer_mode = FIFO_MODE;
+ set_rfr_wm(msm_port);
+ ret = geni_se_init(uport->membase, msm_port->xfer_mode,
msm_port->rx_wm, msm_port->rx_rfr);
- if (ret) {
- dev_err(uport->dev, "%s: Fail\n", __func__);
- goto exit_portsetup;
+ if (ret) {
+ dev_err(uport->dev, "%s: Fail\n", __func__);
+ goto exit_portsetup;
+ }
+ se_get_packing_config(8, 4, false, &cfg0, &cfg1);
+ geni_write_reg_nolog(cfg0, uport->membase,
+ SE_GENI_TX_PACKING_CFG0);
+ geni_write_reg_nolog(cfg1, uport->membase,
+ SE_GENI_TX_PACKING_CFG1);
+ } else {
+ set_rfr_wm(msm_port);
+ se_get_packing_config(8, 1, false, &cfg0, &cfg1);
+ geni_write_reg_nolog(cfg0, uport->membase,
+ SE_GENI_TX_PACKING_CFG0);
+ geni_write_reg_nolog(cfg1, uport->membase,
+ SE_GENI_TX_PACKING_CFG1);
}
-
msm_port->port_setup = true;
/*
* Ensure Port setup related IO completes before returning to
@@ -848,7 +875,7 @@
static void geni_serial_write_term_regs(struct uart_port *uport, u32 loopback,
u32 tx_trans_cfg, u32 tx_parity_cfg, u32 rx_trans_cfg,
u32 rx_parity_cfg, u32 bits_per_char, u32 stop_bit_len,
- u32 rxstale, u32 s_clk_cfg)
+ u32 s_clk_cfg)
{
geni_write_reg_nolog(loopback, uport->membase, SE_UART_LOOPBACK_CFG);
geni_write_reg_nolog(tx_trans_cfg, uport->membase,
@@ -865,7 +892,6 @@
SE_UART_RX_WORD_LEN);
geni_write_reg_nolog(stop_bit_len, uport->membase,
SE_UART_TX_STOP_BIT_LEN);
- geni_write_reg_nolog(rxstale, uport->membase, SE_UART_RX_STALE_CNT);
geni_write_reg_nolog(s_clk_cfg, uport->membase, GENI_SER_M_CLK_CFG);
geni_write_reg_nolog(s_clk_cfg, uport->membase, GENI_SER_S_CLK_CFG);
}
@@ -901,7 +927,6 @@
unsigned int rx_trans_cfg;
unsigned int rx_parity_cfg;
unsigned int stop_bit_len;
- unsigned int rxstale;
unsigned int clk_div;
unsigned long ser_clk_cfg = 0;
struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
@@ -966,8 +991,6 @@
break;
}
- /* stale timer, set this to 16 characters. */
- rxstale = bits_per_char * STALE_TIMEOUT;
/* stop bits */
if (termios->c_cflag & CSTOPB)
@@ -984,7 +1007,7 @@
geni_serial_write_term_regs(uport, port->loopback, tx_trans_cfg,
tx_parity_cfg, rx_trans_cfg, rx_parity_cfg, bits_per_char,
- stop_bit_len, rxstale, ser_clk_cfg);
+ stop_bit_len, ser_clk_cfg);
exit_set_termios:
return;
@@ -1066,7 +1089,6 @@
{
struct uart_port *uport = &dev->port;
int ret = 0;
- struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
u32 tx_trans_cfg = 0;
u32 tx_parity_cfg = 0;
u32 rx_trans_cfg = 0;
@@ -1078,6 +1100,7 @@
u32 baud = 115200;
u32 clk_div;
unsigned long clk_rate;
+ unsigned long cfg0, cfg1;
if (!uport->membase) {
ret = -ENOMEM;
@@ -1089,13 +1112,8 @@
goto exit_geni_serial_earlyconsetup;
}
- msm_port->xfer_mode = FIFO_MODE;
- set_rfr_wm(msm_port);
- msm_port->tx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
- msm_port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
- msm_port->tx_fifo_width = DEF_FIFO_WIDTH_BITS;
- geni_se_init(uport->membase, msm_port->xfer_mode, msm_port->rx_wm,
- msm_port->rx_rfr);
+ geni_se_init(uport->membase, FIFO_MODE, (DEF_FIFO_DEPTH_WORDS >> 1),
+ (DEF_FIFO_DEPTH_WORDS - 2));
/*
* Ignore Flow control.
* Disable Tx Parity.
@@ -1120,6 +1138,9 @@
s_clk_cfg |= SER_CLK_EN;
s_clk_cfg |= (clk_div << CLK_DIV_SHFT);
+ se_get_packing_config(8, 1, false, &cfg0, &cfg1);
+ geni_write_reg_nolog(cfg0, uport->membase, SE_GENI_TX_PACKING_CFG0);
+ geni_write_reg_nolog(cfg1, uport->membase, SE_GENI_TX_PACKING_CFG1);
/*
* Make an unconditional cancel on the main sequencer to reset
@@ -1128,7 +1149,7 @@
msm_geni_serial_poll_cancel_tx(uport);
geni_serial_write_term_regs(uport, 0, tx_trans_cfg,
tx_parity_cfg, rx_trans_cfg, rx_parity_cfg, bits_per_char,
- stop_bit, rx_stale, s_clk_cfg);
+ stop_bit, s_clk_cfg);
dev->con->write = msm_geni_serial_early_console_write;
dev->con->setup = NULL;
@@ -1435,9 +1456,11 @@
struct msm_geni_serial_port *port = platform_get_drvdata(pdev);
struct uart_port *uport = &port->uport;
- if (uart_console(uport))
+ if (uart_console(uport)) {
+ se_geni_resources_on(&port->serial_rsc);
uart_resume_port((struct uart_driver *)uport->private_data,
uport);
+ }
return 0;
}
#else
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index bda14ef..744ea4f 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -125,6 +125,7 @@
* BVEC_POOL_IDX()
*/
#define BIO_RESET_BITS 10
+#define BIO_INLINECRYPT 15
/*
* We support 6 different bvec pools, the last one is magic in that it
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index cb4387d..5a10db5 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -479,11 +479,11 @@
return rx_fifo_depth;
}
-static inline void se_config_packing(void __iomem *base, int bpw,
- int pack_words, bool msb_to_lsb)
+static inline void se_get_packing_config(int bpw, int pack_words,
+ bool msb_to_lsb, unsigned long *cfg0,
+ unsigned long *cfg1)
{
u32 cfg[4] = {0};
- unsigned long cfg0, cfg1;
int len = ((bpw < 8) ? (bpw - 1) : 7);
int idx = ((msb_to_lsb == 1) ? len : 0);
int iter = (bpw * pack_words) >> 3;
@@ -495,8 +495,16 @@
if (i == iter - 1)
cfg[i] |= 1;
}
- cfg0 = cfg[0] | (cfg[1] << 10);
- cfg1 = cfg[2] | (cfg[3] << 10);
+ *cfg0 = cfg[0] | (cfg[1] << 10);
+ *cfg1 = cfg[2] | (cfg[3] << 10);
+}
+
+static inline void se_config_packing(void __iomem *base, int bpw,
+ int pack_words, bool msb_to_lsb)
+{
+ unsigned long cfg0, cfg1;
+
+ se_get_packing_config(bpw, pack_words, msb_to_lsb, &cfg0, &cfg1);
geni_write_reg(cfg0, base, SE_GENI_TX_PACKING_CFG0);
geni_write_reg(cfg1, base, SE_GENI_TX_PACKING_CFG1);
geni_write_reg(cfg0, base, SE_GENI_RX_PACKING_CFG0);
diff --git a/include/linux/sde_rsc.h b/include/linux/sde_rsc.h
index 60cc768..f3fa9e6 100644
--- a/include/linux/sde_rsc.h
+++ b/include/linux/sde_rsc.h
@@ -79,6 +79,7 @@
* @current_state: current client state
* @crtc_id: crtc_id associated with this rsc client.
* @rsc_index: rsc index of a client - only index "0" valid.
+ * @id: Index of client. It will be assigned during client_create call
* @list: list to attach client master list
*/
struct sde_rsc_client {
@@ -86,6 +87,7 @@
short current_state;
int crtc_id;
u32 rsc_index;
+ u32 id;
struct list_head list;
};
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index e318878..35ad69f 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -70,7 +70,7 @@
MODULE_PARM_DESC(bss_entries_limit,
"limit to number of scan BSS entries (per wiphy, default 1000)");
-#define IEEE80211_SCAN_RESULT_EXPIRE (7 * HZ)
+#define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ)
static void bss_free(struct cfg80211_internal_bss *bss)
{