aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnusha Shakarad <ashaka@codeaurora.org>2019-03-11 13:38:18 +0530
committerAnusha Shakarad <ashaka@codeaurora.org>2019-03-11 14:45:37 +0530
commita9ec0eb5213125786dbb980a44194d7754a56cdf (patch)
tree6169679c401442372b22491892d1f50bfb6e504e
parent976be12b72ca2e1f5479e26aeac8e1b1c12dc41b (diff)
parentbb9a1580bc7a832857447b4ec5edd05e10fd2c50 (diff)
Merge commit 'bb9a1580bc7a832857447b4ec5edd05e10fd2c50' into HEADLA.UM.7.6.2.r1-07300-89xx.0
Change-Id: I9ece2dc58a2466e56427801f9ba35249e383bcbd Signed-off-by: Anusha Shakarad <ashaka@codeaurora.org>
-rw-r--r--Documentation/devicetree/bindings/media/video/msm-cam-ife-csid.txt3
-rw-r--r--Documentation/devicetree/bindings/media/video/msm-cam-vfe.txt3
-rw-r--r--Documentation/devicetree/bindings/power/supply/qcom/smb1360-charger-fg.txt22
-rw-r--r--arch/arm/configs/msm8909w-perf_defconfig1
-rw-r--r--arch/arm64/boot/dts/qcom/qcs605.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/qm215-qrd-smb1360.dtsi30
-rw-r--r--arch/arm64/boot/dts/qcom/sdm670-camera-sensor-qrd.dtsi7
-rw-r--r--arch/arm64/kernel/perf_event.c4
-rw-r--r--arch/arm64/mm/dma-mapping.c24
-rw-r--r--drivers/char/diag/diag_dci.c32
-rw-r--r--drivers/char/diag/diag_dci.h3
-rw-r--r--drivers/char/diag/diag_usb.c6
-rw-r--r--drivers/char/diag/diagchar.h6
-rw-r--r--drivers/char/diag/diagchar_core.c14
-rw-r--r--drivers/char/diag/diagfwd.c4
-rw-r--r--drivers/char/diag/diagmem.c4
-rw-r--r--drivers/gpu/drm/msm/dp/dp_ctrl.c4
-rw-r--r--drivers/gpu/drm/msm/sde_hdcp_1x.c4
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.c10
-rw-r--r--drivers/gpu/msm/kgsl_snapshot.c6
-rw-r--r--drivers/iommu/dma-iommu.c5
-rw-r--r--drivers/iommu/iommu-debug.c10
-rw-r--r--drivers/leds/leds-qpnp-vibrator.c1
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_hw_core.c30
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_virtual_core.c10
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_core/cam_context.c9
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c20
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_core/cam_core_defs.h44
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_core/cam_node.c6
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c18
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c21
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v150_100.h537
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v175_120.h769
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_fd/Makefile2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/Makefile2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c32
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/Makefile2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c6
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_session_defs.h3
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/hfi.c11
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/bps_hw/bps_core.c9
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c36
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h12
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/ipe_hw/ipe_core.c8
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c719
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.h5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c766
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h11
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c156
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h17
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h28
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.c61
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h (renamed from drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.h)180
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h369
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c23
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c282
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h23
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.c59
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c6
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h26
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h22
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c102
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h6
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c93
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h12
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/Makefile14
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c52
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.c52
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.h336
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h (renamed from drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h)264
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h1117
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe17x.c16
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c18
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c1239
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h143
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c33
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h11
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile1
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c15
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c163
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c638
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.h94
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c10
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c226
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h6
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c12
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_lrme/Makefile2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_lrme/cam_lrme_context.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/Makefile2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c15
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c14
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr.c14
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr_api.h11
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c740
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h29
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.c6
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.h5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c103
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_dev.c35
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_core.c166
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.c3
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.h7
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c57
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c11
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h10
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c142
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c28
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c426
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.h11
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c17
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.h7
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_soc.c122
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c97
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_dev.c28
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_res_mgr/cam_res_mgr.c14
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c155
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c19
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c160
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c20
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_utils/Makefile1
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_utils/cam_cx_ipeak.c135
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_utils/cam_cx_ipeak.h (renamed from drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_log.h)22
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.c97
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.h10
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.c80
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.h8
-rw-r--r--drivers/media/platform/msm/vidc/hfi_response_handler.c53
-rw-r--r--drivers/media/platform/msm/vidc_3x/hfi_response_handler.c53
-rw-r--r--drivers/media/platform/msm/vidc_3x/msm_vidc.c7
-rw-r--r--drivers/media/platform/msm/vidc_3x/msm_vidc_common.c4
-rw-r--r--drivers/misc/hdcp_qseecom.c26
-rw-r--r--drivers/mmc/host/cmdq_hci.c12
-rw-r--r--drivers/perf/arm_pmu.c14
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_intf.c21
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_intf.c19
-rw-r--r--drivers/power/supply/qcom/qpnp-smb2.c8
-rw-r--r--drivers/power/supply/qcom/qpnp-smb5.c2
-rw-r--r--drivers/power/supply/qcom/qpnp-smbcharger.c39
-rw-r--r--drivers/power/supply/qcom/smb-lib.c1
-rw-r--r--drivers/power/supply/qcom/smb1360-charger-fg.c84
-rw-r--r--drivers/scsi/ufs/ufs-qcom-ice.c36
-rw-r--r--drivers/scsi/ufs/ufshcd.c57
-rw-r--r--drivers/slimbus/slim-msm-ngd.c20
-rw-r--r--drivers/soc/qcom/glink_spi_xprt.c33
-rw-r--r--drivers/soc/qcom/icnss.c44
-rw-r--r--drivers/spmi/spmi-pmic-arb-debug.c14
-rw-r--r--drivers/video/fbdev/msm/mdp3_ctrl.c23
-rw-r--r--drivers/video/fbdev/msm/mdp3_ctrl.h7
-rw-r--r--fs/proc/inode.c9
-rw-r--r--fs/proc/internal.h3
-rw-r--r--fs/proc/root.c52
-rw-r--r--include/linux/hdcp_qseecom.h3
-rw-r--r--include/linux/perf_event.h14
-rw-r--r--include/soc/qcom/icnss.h3
-rw-r--r--include/uapi/media/cam_defs.h3
-rw-r--r--include/uapi/media/cam_isp.h39
-rw-r--r--include/uapi/media/cam_isp_ife.h6
-rw-r--r--include/uapi/media/cam_req_mgr.h2
-rw-r--r--kernel/cpu.c2
-rw-r--r--kernel/events/core.c207
-rw-r--r--mm/memory.c2
-rw-r--r--net/wireless/db.txt308
177 files changed, 10744 insertions, 2603 deletions
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-ife-csid.txt b/Documentation/devicetree/bindings/media/video/msm-cam-ife-csid.txt
index 29ea987e306d..8aa0ec530a3a 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cam-ife-csid.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cam-ife-csid.txt
@@ -15,7 +15,8 @@ First Level Node - CAM IFE CSID device
- compatible
Usage: required
Value type: <string>
- Definition: Should be "qcom,csid170" or "qcom,csid-lite170".
+ Definition: Should be "qcom,csid170", "qcom,csid175", "qcom,csid175_200",
+ "qcom,csid-lite170" or "qcom,csid-lite175".
- cell-index
Usage: required
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-vfe.txt b/Documentation/devicetree/bindings/media/video/msm-cam-vfe.txt
index f156cc67b2aa..9750d63794d1 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cam-vfe.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cam-vfe.txt
@@ -17,7 +17,8 @@ Required properties:
Usage: required
Value type: <string>
Definition: Should specify the compatibility string for matching the
- driver. e.g. "qcom,vfe170", "qcom,vfe-lite170".
+ driver. e.g. "qcom,vfe175", "qcom,vfe170", "qcom,vfe175_130",
+ "qcom,vfe-lite175", "qcom,vfe-lite175_130", "qcom,vfe-lite170".
- cell-index
Usage: required
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/smb1360-charger-fg.txt b/Documentation/devicetree/bindings/power/supply/qcom/smb1360-charger-fg.txt
index 8b2234e0c9fe..326f279623eb 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/smb1360-charger-fg.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/smb1360-charger-fg.txt
@@ -13,12 +13,15 @@ Required Properties:
Optional Properties:
-- interrupts This indicates the IRQ number of the GPIO
- connected to the STAT pin.
+- interrupts This indicates the IRQ numbers of the GPIOs
+ connected to the STAT and usb-id pins.
+- interrupt-names The irq names should be smb1360_stat_irq and
+ smb1360_usb_id_irq.The stat irq is mandatory
+ and usb_id irq is optional.
- pinctrl-names: The state name of the pin configuration. Only
support: "default".
-- pinctrl-0: The phandle of the pin configuration node in
- pinctrl for smb_int_pin.
+- pinctrl-0: The phandles of the pin configuration node in
+ pinctrl for smb_int_pin and usb-id pin.
For details of pinctrl properties, please refer to:
"Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt"
- qcom,float-voltage-mv Float Voltage in mV - the maximum voltage up to which
@@ -177,6 +180,8 @@ Optional Properties:
Please go through the documentation for PMIC gpio
configuration details:
Documentation/devicetree/bindings/gpio/qpnp-pin.txt
+- qcom,usb-id-gpio GPIO for usb-id detection.This property is mandatory
+ if usb-id irq is specified.
- qcom,parallel-charging-enabled: A bool property which enables SMB1360 to
operate in the parallel mode. SMB1360 acts
as the primary charger.
@@ -192,9 +197,13 @@ Example:
compatible = "qcom,smb1360-chg-fg";
reg = <0x1b>;
interrupt-parent = <&spmi_bus>;
- interrupts = <0x00 0xcd 0>;
+ interrupts = <0x00 0xcd 0>,
+ <0 0xc3 0 3>;
+ interrupt-names = "smb1360_stat_irq",
+ "smb1360_usb_id_irq";
pinctrl-names = "default";
- pinctrl-0 = <&smb_int_default>;
+ pinctrl-0 = <&smb_int_default>,
+ <&usb_id_default>;
/* battery-profile selection properties */
qcom,batt-profile-select;
@@ -242,5 +251,6 @@ Example:
qcom,otg-fet-present;
qcom,otg-fet-enable-gpio = <&pm8916_gpios 3 0>;
+ qcom,usb-id-gpio = <&pm8916_gpios 4 0>;
};
};
diff --git a/arch/arm/configs/msm8909w-perf_defconfig b/arch/arm/configs/msm8909w-perf_defconfig
index 084e48707f58..8a5099dc084a 100644
--- a/arch/arm/configs/msm8909w-perf_defconfig
+++ b/arch/arm/configs/msm8909w-perf_defconfig
@@ -329,7 +329,6 @@ CONFIG_FB_MSM_MDSS=y
CONFIG_FB_MSM_MDSS_WRITEBACK=y
CONFIG_FB_MSM_MDSS_SPI_PANEL=y
CONFIG_FB_MSM_MDSS_MDP3=y
-CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_SOUND=y
diff --git a/arch/arm64/boot/dts/qcom/qcs605.dtsi b/arch/arm64/boot/dts/qcom/qcs605.dtsi
index 7801775c7e3b..c437ef1dbfac 100644
--- a/arch/arm64/boot/dts/qcom/qcs605.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, 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
@@ -59,7 +59,7 @@
};
&secure_display_memory {
- status = "disabled";
+ size = <0 0xa000000>;
};
&sp_mem {
diff --git a/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360.dtsi b/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360.dtsi
index 285f91a3e300..06aadee8c948 100644
--- a/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360.dtsi
+++ b/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360.dtsi
@@ -37,26 +37,48 @@
};
};
+&pm8916_gpios {
+ usb_id {
+ usb_id_default: usb_id_default {
+ pins = "gpio4";
+ function = "normal";
+ input-enable;
+ bias-pull-up;
+ power-source = <0>;
+ };
+ };
+};
+
&i2c_2 {
status ="ok";
smb1360_otg_supply: smb1360-chg-fg@14 {
compatible = "qcom,smb1360-chg-fg";
reg = <0x14>;
- interrupt-parent = <&tlmm>;
- interrupts = <13 8>;
+ interrupts-extended = <&tlmm 13 8>,
+ <&spmi_bus 0 0xc3 0 3>;
+ interrupt-names = "smb1360_stat_irq",
+ "smb1360_usb_id_irq";
pinctrl-names = "default";
- pinctrl-0 = <&smb_int_default>;
+ pinctrl-0 = <&smb_int_default>,
+ <&usb_id_default>;
qcom,empty-soc-disabled;
qcom,chg-inhibit-disabled;
qcom,float-voltage-mv = <4400>;
qcom,iterm-ma = <100>;
qcom,recharge-thresh-mv = <100>;
qcom,thermal-mitigation = <1500 700 600 0>;
- regulator-name = "smb1360_otg_vreg";
qcom,fg-batt-capacity-mah = <2800>;
qcom,fg-cutoff-voltage-mv = <3400>;
qcom,fg-iterm-ma = <130>;
qcom,fg-delta-soc = <1>;
+ qcom,usb-id-gpio = <&pm8916_gpios 4 0>;
+ qcom,soft-jeita-supported;
+ qcom,warm-bat-decidegc = <450>;
+ qcom,cool-bat-decidegc = <150>;
+ qcom,warm-bat-mv = <4200>;
+ qcom,cool-bat-mv = <4200>;
+ qcom,warm-bat-ma = <1000>;
+ qcom,cool-bat-ma = <1000>;
status= "okay";
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-qrd.dtsi
index 78047bd22f9e..fd0aa8a39a33 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-qrd.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, 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
@@ -194,6 +194,11 @@
};
&cam_cci {
+ qcom,cam-res-mgr {
+ compatible = "qcom,cam-res-mgr";
+ status = "ok";
+ };
+
actuator_rear: qcom,actuator@0 {
cell-index = <0>;
reg = <0x0>;
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index e0b731e70f66..c845bf57ccb3 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -779,8 +779,8 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev)
struct perf_event *event = cpuc->events[idx];
struct hw_perf_event *hwc;
- /* Ignore if we don't have an event or if it's a zombie event */
- if (!event || event->state == PERF_EVENT_STATE_ZOMBIE)
+ /* Ignore if we don't have an event */
+ if (!event || event->state != PERF_EVENT_STATE_ACTIVE)
continue;
/*
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 42dde2d64166..c38c08ee630d 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -1256,6 +1256,9 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
size_t array_size = count * sizeof(struct page *);
int i = 0;
bool is_coherent = is_dma_coherent(dev, attrs);
+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
+ unsigned int alloc_sizes = mapping->domain->pgsize_bitmap;
+ unsigned long order_mask;
if (array_size <= PAGE_SIZE)
pages = kzalloc(array_size, gfp);
@@ -1284,13 +1287,26 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
* IOMMU can map any pages, so himem can also be used here
*/
gfp |= __GFP_NOWARN | __GFP_HIGHMEM;
+ order_mask = alloc_sizes >> PAGE_SHIFT;
+ order_mask &= (2U << MAX_ORDER) - 1;
+ if (!order_mask)
+ goto error;
while (count) {
- int j, order = __fls(count);
+ int j, order;
+
+ order_mask &= (2U << __fls(count)) - 1;
+ order = __fls(order_mask);
+
+ pages[i] = alloc_pages(order ? (gfp | __GFP_NORETRY) &
+ ~__GFP_RECLAIM : gfp, order);
+ while (!pages[i] && order) {
+ order_mask &= ~(1U << order);
+ order = __fls(order_mask);
+ pages[i] = alloc_pages(order ? (gfp | __GFP_NORETRY) &
+ ~__GFP_RECLAIM : gfp, order);
+ }
- pages[i] = alloc_pages(gfp, order);
- while (!pages[i] && order)
- pages[i] = alloc_pages(gfp, --order);
if (!pages[i])
goto error;
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 0937b2f14d77..5a1afd0e41c7 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, 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
@@ -2757,10 +2757,11 @@ err:
int diag_dci_init(void)
{
- int ret = 0;
+ int ret = 0, i;
driver->dci_tag = 0;
- driver->dci_client_id = 0;
+ for (i = 0; i < MAX_DCI_CLIENTS; i++)
+ driver->dci_client_id[i] = 0;
driver->num_dci_client = 0;
mutex_init(&driver->dci_mutex);
mutex_init(&dci_log_mask_mutex);
@@ -2956,8 +2957,8 @@ int diag_dci_register_client(struct diag_dci_reg_tbl_t *reg_entry)
mutex_init(&new_entry->write_buf_mutex);
new_entry->dci_log_mask = vzalloc(DCI_LOG_MASK_SIZE);
if (!new_entry->dci_log_mask) {
- pr_err("diag: Unable to create log mask for client, %d",
- driver->dci_client_id);
+ pr_err("diag: Unable to create log mask for DCI client, tgid: %d\n",
+ current->tgid);
goto fail_alloc;
}
create_dci_log_mask_tbl(new_entry->dci_log_mask, DCI_LOG_MASK_CLEAN);
@@ -3006,17 +3007,24 @@ int diag_dci_register_client(struct diag_dci_reg_tbl_t *reg_entry)
proc_buf->buf_curr = proc_buf->buf_primary;
}
- list_add_tail(&new_entry->track, &driver->dci_client_list);
- driver->dci_client_id++;
- new_entry->client_info.client_id = driver->dci_client_id;
- reg_entry->client_id = driver->dci_client_id;
+ for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+ if (driver->dci_client_id[i] == 0)
+ break;
+ }
+
+ if (i == MAX_DCI_CLIENTS)
+ goto fail_alloc;
+ driver->dci_client_id[i] = 1;
+ new_entry->client_info.client_id = i+1;
+ reg_entry->client_id = i+1;
driver->num_dci_client++;
+ list_add_tail(&new_entry->track, &driver->dci_client_list);
if (driver->num_dci_client == 1)
diag_update_proc_vote(DIAG_PROC_DCI, VOTE_UP, reg_entry->token);
queue_work(driver->diag_real_time_wq, &driver->diag_real_time_work);
mutex_unlock(&driver->dci_mutex);
- return driver->dci_client_id;
+ return reg_entry->client_id;
fail_alloc:
if (new_entry) {
@@ -3075,7 +3083,11 @@ int diag_dci_deinit_client(struct diag_dci_client_tbl *entry)
*/
if (!list_empty(&entry->track))
list_del(&entry->track);
+
+ if (entry->client_info.client_id > MAX_DCI_CLIENTS)
+ return DIAG_DCI_NO_REG;
driver->num_dci_client--;
+ driver->dci_client_id[entry->client_info.client_id - 1] = 0;
/*
* Clear the client's log and event masks, update the cumulative
* masks and send the masks to peripherals
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 2fb0e3f7adf3..835c0c1708cf 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, 2018-2019 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
@@ -12,7 +12,6 @@
#ifndef DIAG_DCI_H
#define DIAG_DCI_H
-#define MAX_DCI_CLIENTS 10
#define DCI_PKT_RSP_CODE 0x93
#define DCI_DELAYED_RSP_CODE 0x94
#define DCI_CONTROL_PKT_CODE 0x9A
diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c
index 24a9f8af728a..b8b8b3206528 100644
--- a/drivers/char/diag/diag_usb.c
+++ b/drivers/char/diag/diag_usb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 2018-2019 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
@@ -324,8 +324,8 @@ static void diag_usb_write_done(struct diag_usb_info *ch,
DIAG_LOG(DIAG_DEBUG_MUX, "partial write_done ref %d\n",
atomic_read(&entry->ref_count));
diag_ws_on_copy_complete(DIAG_WS_MUX);
- spin_unlock_irqrestore(&ch->write_lock, flags);
diagmem_free(driver, req, ch->mempool);
+ spin_unlock_irqrestore(&ch->write_lock, flags);
return;
}
DIAG_LOG(DIAG_DEBUG_MUX, "full write_done, ctxt: %d\n",
@@ -343,8 +343,8 @@ static void diag_usb_write_done(struct diag_usb_info *ch,
buf = NULL;
len = 0;
ctxt = 0;
- spin_unlock_irqrestore(&ch->write_lock, flags);
diagmem_free(driver, req, ch->mempool);
+ spin_unlock_irqrestore(&ch->write_lock, flags);
}
static void diag_usb_notifier(void *priv, unsigned int event,
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index f63d78c32b6e..5fb01ac66376 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2019, 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
@@ -288,6 +288,7 @@ for (i = 0; i <= fwd_info->num_pd - 2; i++) \
#define DIAG_CNTL_TYPE 2
#define DIAG_DCI_TYPE 3
+#define MAX_DCI_CLIENTS 10
/*
* List of diag ids
* 0 is reserved for unknown diag id, 1 for apps, diag ids
@@ -580,7 +581,7 @@ struct diagchar_dev {
struct list_head dci_req_list;
struct list_head dci_client_list;
int dci_tag;
- int dci_client_id;
+ int dci_client_id[MAX_DCI_CLIENTS];
struct mutex dci_mutex;
int num_dci_client;
unsigned char *apps_dci_buf;
@@ -597,6 +598,7 @@ struct diagchar_dev {
unsigned int poolsize_hdlc;
unsigned int poolsize_dci;
unsigned int poolsize_user;
+ spinlock_t diagmem_lock;
/* Buffers for masks */
struct mutex diag_cntl_mutex;
/* Members for Sending response */
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 8adaf6478acb..8cf425db1589 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -213,17 +213,19 @@ static void drain_timer_func(unsigned long data)
static void diag_drain_apps_data(struct diag_apps_data_t *data)
{
int err = 0;
+ unsigned long flags;
if (!data || !data->buf)
return;
err = diag_mux_write(DIAG_LOCAL_PROC, data->buf, data->len,
data->ctxt);
+ spin_lock_irqsave(&driver->diagmem_lock, flags);
if (err)
diagmem_free(driver, data->buf, POOL_TYPE_HDLC);
-
data->buf = NULL;
data->len = 0;
+ spin_unlock_irqrestore(&driver->diagmem_lock, flags);
}
void diag_update_user_client_work_fn(struct work_struct *work)
@@ -294,6 +296,8 @@ static void diag_mempool_init(void)
diagmem_init(driver, POOL_TYPE_HDLC);
diagmem_init(driver, POOL_TYPE_USER);
diagmem_init(driver, POOL_TYPE_DCI);
+
+ spin_lock_init(&driver->diagmem_lock);
}
static void diag_mempool_exit(void)
@@ -2744,6 +2748,7 @@ static int diag_process_apps_data_hdlc(unsigned char *buf, int len,
struct diag_apps_data_t *data = &hdlc_data;
struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
+ unsigned long flags;
/*
* The maximum encoded size of the buffer can be atmost twice the length
* of the packet. Add three bytes foe footer - 16 bit CRC (2 bytes) +
@@ -2848,10 +2853,11 @@ static int diag_process_apps_data_hdlc(unsigned char *buf, int len,
return PKT_ALLOC;
fail_free_buf:
+ spin_lock_irqsave(&driver->diagmem_lock, flags);
diagmem_free(driver, data->buf, POOL_TYPE_HDLC);
data->buf = NULL;
data->len = 0;
-
+ spin_unlock_irqrestore(&driver->diagmem_lock, flags);
fail_ret:
return ret;
}
@@ -2863,6 +2869,7 @@ static int diag_process_apps_data_non_hdlc(unsigned char *buf, int len,
int ret = PKT_DROP;
struct diag_pkt_frame_t header;
struct diag_apps_data_t *data = &non_hdlc_data;
+ unsigned long flags;
/*
* The maximum packet size, when the data is non hdlc encoded is equal
* to the size of the packet frame header and the length. Add 1 for the
@@ -2927,10 +2934,11 @@ static int diag_process_apps_data_non_hdlc(unsigned char *buf, int len,
return PKT_ALLOC;
fail_free_buf:
+ spin_lock_irqsave(&driver->diagmem_lock, flags);
diagmem_free(driver, data->buf, POOL_TYPE_HDLC);
data->buf = NULL;
data->len = 0;
-
+ spin_unlock_irqrestore(&driver->diagmem_lock, flags);
fail_ret:
return ret;
}
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index f1bc1c5047e1..d637405a71d1 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2019, 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
@@ -1823,9 +1823,11 @@ static int diagfwd_mux_write_done(unsigned char *buf, int len, int buf_ctxt,
diagfwd_write_done(peripheral, type, num);
diag_ws_on_copy(DIAG_WS_MUX);
} else if (peripheral == APPS_DATA) {
+ spin_lock_irqsave(&driver->diagmem_lock, flags);
diagmem_free(driver, (unsigned char *)buf,
POOL_TYPE_HDLC);
buf = NULL;
+ spin_unlock_irqrestore(&driver->diagmem_lock, flags);
} else {
pr_err_ratelimited("diag: Invalid peripheral %d in %s, type: %d\n",
peripheral, __func__, type);
diff --git a/drivers/char/diag/diagmem.c b/drivers/char/diag/diagmem.c
index ada645d92104..2a3602568a1d 100644
--- a/drivers/char/diag/diagmem.c
+++ b/drivers/char/diag/diagmem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2014, 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2014, 2016, 2019 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
@@ -221,7 +221,7 @@ void diagmem_free(struct diagchar_dev *driver, void *buf, int pool_type)
break;
}
spin_lock_irqsave(&mempool->lock, flags);
- if (mempool->count > 0) {
+ if (mempool->count > 0 && buf) {
mempool_free(buf, mempool->pool);
atomic_add(-1, (atomic_t *)&mempool->count);
} else {
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index f2e9085cb5a2..8e8896479cce 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -1306,9 +1306,7 @@ static void dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl)
u32 pattern_sent = 0x0;
u32 pattern_requested = ctrl->link->phy_params.phy_test_pattern_sel;
- ctrl->catalog->update_vx_px(ctrl->catalog,
- ctrl->link->phy_params.v_level,
- ctrl->link->phy_params.p_level);
+ dp_ctrl_update_vx_px(ctrl);
ctrl->catalog->send_phy_pattern(ctrl->catalog, pattern_requested);
ctrl->link->send_test_response(ctrl->link);
diff --git a/drivers/gpu/drm/msm/sde_hdcp_1x.c b/drivers/gpu/drm/msm/sde_hdcp_1x.c
index 2c7f52c7970b..53e20e261ebd 100644
--- a/drivers/gpu/drm/msm/sde_hdcp_1x.c
+++ b/drivers/gpu/drm/msm/sde_hdcp_1x.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2019, 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
@@ -1263,6 +1263,8 @@ static void sde_hdcp_1x_off(void *input)
hdcp->sink_r0_ready = false;
+ hdcp1_unload_app();
+
pr_debug("%s: HDCP: Off\n", SDE_HDCP_STATE_NAME);
} /* hdcp_1x_off */
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 2a149ac87ed1..06403a87bec8 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2019, 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
@@ -64,7 +64,7 @@ static const char * const clocks[] = {
"ahb_clk"
};
-static unsigned int ib_votes[KGSL_MAX_BUSLEVELS];
+static unsigned long ib_votes[KGSL_MAX_BUSLEVELS];
static int last_vote_buslevel;
static int max_vote_buslevel;
@@ -127,7 +127,7 @@ static void _record_pwrevent(struct kgsl_device *device,
/**
* kgsl_get_bw() - Return latest msm bus IB vote
*/
-static unsigned int kgsl_get_bw(void)
+static unsigned long kgsl_get_bw(void)
{
return ib_votes[last_vote_buslevel];
}
@@ -141,8 +141,8 @@ static unsigned int kgsl_get_bw(void)
static void _ab_buslevel_update(struct kgsl_pwrctrl *pwr,
unsigned long *ab)
{
- unsigned int ib = ib_votes[last_vote_buslevel];
- unsigned int max_bw = ib_votes[max_vote_buslevel];
+ unsigned long ib = ib_votes[last_vote_buslevel];
+ unsigned long max_bw = ib_votes[max_vote_buslevel];
if (!ab)
return;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 0ed17d859080..099daaf8403a 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, 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
@@ -335,10 +335,8 @@ int kgsl_snapshot_get_object(struct kgsl_snapshot *snapshot,
entry = kgsl_sharedmem_find(process, gpuaddr);
- if (entry == NULL) {
- KGSL_CORE_ERR("Unable to find GPU buffer 0x%016llX\n", gpuaddr);
+ if (entry == NULL)
return -EINVAL;
- }
/* We can't freeze external memory, because we don't own it */
if (entry->memdesc.flags & KGSL_MEMFLAGS_USERMEM_MASK)
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 36c84df078c7..30815df2ba6b 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -369,8 +369,9 @@ static struct page **__iommu_dma_alloc_pages(unsigned int count,
unsigned int order = __fls(order_mask);
order_size = 1U << order;
- page = alloc_pages((order_mask - order_size) ?
- gfp | __GFP_NORETRY : gfp, order);
+ page = alloc_pages(order ?
+ (gfp | __GFP_NORETRY) &
+ ~__GFP_RECLAIM : gfp, order);
if (!page)
continue;
if (!order)
diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c
index 2dcac176812c..87a1244206ba 100644
--- a/drivers/iommu/iommu-debug.c
+++ b/drivers/iommu/iommu-debug.c
@@ -1395,7 +1395,7 @@ static ssize_t iommu_debug_test_virt_addr_read(struct file *file,
else
snprintf(buf, buf_len, "0x%pK\n", test_virt_addr);
- buflen = min(count, strlen(buf)+1);
+ buflen = min(count, strlen(buf));
if (copy_to_user(ubuf, buf, buflen)) {
pr_err("Couldn't copy_to_user\n");
retval = -EFAULT;
@@ -1518,7 +1518,7 @@ static ssize_t iommu_debug_pte_read(struct file *file, char __user *ubuf,
else
snprintf(buf, sizeof(buf), "pte=%016llx\n", pte);
- buflen = min(count, strlen(buf)+1);
+ buflen = min(count, strlen(buf));
if (copy_to_user(ubuf, buf, buflen)) {
pr_err("Couldn't copy_to_user\n");
retval = -EFAULT;
@@ -1587,7 +1587,7 @@ static ssize_t iommu_debug_atos_read(struct file *file, char __user *ubuf,
snprintf(buf, 100, "%pa\n", &phys);
}
- buflen = min(count, strlen(buf)+1);
+ buflen = min(count, strlen(buf));
if (copy_to_user(ubuf, buf, buflen)) {
pr_err("Couldn't copy_to_user\n");
retval = -EFAULT;
@@ -1640,7 +1640,7 @@ static ssize_t iommu_debug_dma_atos_read(struct file *file, char __user *ubuf,
else
snprintf(buf, sizeof(buf), "%pa\n", &phys);
- buflen = min(count, strlen(buf)+1);
+ buflen = min(count, strlen(buf));
if (copy_to_user(ubuf, buf, buflen)) {
pr_err("Couldn't copy_to_user\n");
retval = -EFAULT;
@@ -1873,7 +1873,7 @@ static ssize_t iommu_debug_dma_map_read(struct file *file, char __user *ubuf,
iova = ddev->iova;
snprintf(buf, sizeof(buf), "%pa\n", &iova);
- buflen = min(count, strlen(buf)+1);
+ buflen = min(count, strlen(buf));
if (copy_to_user(ubuf, buf, buflen)) {
pr_err("Couldn't copy_to_user\n");
retval = -EFAULT;
diff --git a/drivers/leds/leds-qpnp-vibrator.c b/drivers/leds/leds-qpnp-vibrator.c
index d8dcdf6e0b9a..c428bfb386b9 100644
--- a/drivers/leds/leds-qpnp-vibrator.c
+++ b/drivers/leds/leds-qpnp-vibrator.c
@@ -398,7 +398,6 @@ static ssize_t qpnp_vib_set_activate(struct device *dev,
(vib->vib_play_ms % 1000) * 1000000),
HRTIMER_MODE_REL);
}
- vib->vib_play_ms = 0;
mutex_unlock(&vib->lock);
schedule_work(&vib->work);
diff --git a/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_hw_core.c b/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_hw_core.c
index 13a653ae0399..e1809a1d789c 100644
--- a/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_hw_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_hw_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -509,8 +509,8 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw,
if (!rc) {
CAM_DBG(CAM_CDM,
- "write BL success for cnt=%d with tag=%d",
- i, core->bl_tag);
+ "write BL success for cnt=%d with tag=%d total_cnt=%d",
+ i, core->bl_tag, req->data->cmd_arrary_count);
CAM_DBG(CAM_CDM, "Now commit the BL");
if (cam_hw_cdm_commit_bl_write(cdm_hw)) {
@@ -550,35 +550,33 @@ static void cam_hw_cdm_work(struct work_struct *work)
cdm_hw = payload->hw;
core = (struct cam_cdm *)cdm_hw->core_info;
- CAM_DBG(CAM_CDM, "IRQ status=%x", payload->irq_status);
+ CAM_DBG(CAM_CDM, "IRQ status=0x%x", payload->irq_status);
if (payload->irq_status &
CAM_CDM_IRQ_STATUS_INFO_INLINE_IRQ_MASK) {
- struct cam_cdm_bl_cb_request_entry *node;
+ struct cam_cdm_bl_cb_request_entry *node, *tnode;
- CAM_DBG(CAM_CDM, "inline IRQ data=%x",
+ CAM_DBG(CAM_CDM, "inline IRQ data=0x%x",
payload->irq_data);
mutex_lock(&cdm_hw->hw_mutex);
- node = cam_cdm_find_request_by_bl_tag(
- payload->irq_data,
- &core->bl_request_list);
- if (node) {
+ list_for_each_entry_safe(node, tnode,
+ &core->bl_request_list, entry) {
if (node->request_type ==
CAM_HW_CDM_BL_CB_CLIENT) {
cam_cdm_notify_clients(cdm_hw,
CAM_CDM_CB_STATUS_BL_SUCCESS,
(void *)node);
} else if (node->request_type ==
- CAM_HW_CDM_BL_CB_INTERNAL) {
+ CAM_HW_CDM_BL_CB_INTERNAL) {
CAM_ERR(CAM_CDM,
"Invalid node=%pK %d", node,
node->request_type);
}
list_del_init(&node->entry);
+ if (node->bl_tag == payload->irq_data) {
+ kfree(node);
+ break;
+ }
kfree(node);
- } else {
- CAM_ERR(CAM_CDM,
- "Inval node, inline_irq st=%x data=%x",
- payload->irq_status, payload->irq_data);
}
mutex_unlock(&cdm_hw->hw_mutex);
}
@@ -684,7 +682,7 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data)
CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ cmd");
work_status = queue_work(cdm_core->work_queue, &payload->work);
if (work_status == false) {
- CAM_ERR(CAM_CDM, "Failed to queue work for irq=%x",
+ CAM_ERR(CAM_CDM, "Failed to queue work for irq=0x%x",
payload->irq_status);
kfree(payload);
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_virtual_core.c b/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_virtual_core.c
index 9021ecabb27c..b2575825f983 100644
--- a/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_virtual_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_virtual_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -118,6 +118,14 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw,
if ((!rc) && (vaddr_ptr) && (len) &&
(len >= cdm_cmd->cmd[i].offset)) {
+
+
+ if ((len - cdm_cmd->cmd[i].offset) <=
+ cdm_cmd->cmd[i].len) {
+ CAM_ERR(CAM_CDM, "Not enough buffer");
+ rc = -EINVAL;
+ break;
+ }
CAM_DBG(CAM_CDM,
"hdl=%x vaddr=%pK offset=%d cmdlen=%d:%zu",
cdm_cmd->cmd[i].bl_addr.mem_handle,
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c b/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c
index d4f9b72f99f3..5f9d1e06d8a8 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -43,7 +43,6 @@ int cam_context_shutdown(struct cam_context *ctx)
int rc = 0;
struct cam_release_dev_cmd cmd;
- mutex_lock(&ctx->ctx_mutex);
if (ctx->state > CAM_CTX_AVAILABLE && ctx->state < CAM_CTX_STATE_MAX) {
cmd.session_handle = ctx->session_hdl;
cmd.dev_handle = ctx->dev_hdl;
@@ -60,7 +59,6 @@ int cam_context_shutdown(struct cam_context *ctx)
ctx->dev_name, ctx->ctx_id, ctx->state);
rc = -EINVAL;
}
- mutex_unlock(&ctx->ctx_mutex);
rc = cam_destroy_device_hdl(ctx->dev_hdl);
if (rc)
@@ -173,6 +171,7 @@ int cam_context_handle_crm_apply_req(struct cam_context *ctx,
return -EINVAL;
}
+ mutex_lock(&ctx->ctx_mutex);
if (ctx->state_machine[ctx->state].crm_ops.apply_req) {
rc = ctx->state_machine[ctx->state].crm_ops.apply_req(ctx,
apply);
@@ -181,6 +180,7 @@ int cam_context_handle_crm_apply_req(struct cam_context *ctx,
ctx->dev_hdl, ctx->state);
rc = -EPROTO;
}
+ mutex_unlock(&ctx->ctx_mutex);
return rc;
}
@@ -243,6 +243,7 @@ int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova,
return -EINVAL;
}
+ mutex_lock(&ctx->ctx_mutex);
if (ctx->state_machine[ctx->state].pagefault_ops) {
rc = ctx->state_machine[ctx->state].pagefault_ops(ctx, iova,
buf_info);
@@ -250,6 +251,7 @@ int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova,
CAM_WARN(CAM_CORE, "No dump ctx in dev %d, state %d",
ctx->dev_hdl, ctx->state);
}
+ mutex_unlock(&ctx->ctx_mutex);
return rc;
}
@@ -528,6 +530,7 @@ int cam_context_init(struct cam_context *ctx,
ctx->dev_name = dev_name;
ctx->dev_id = dev_id;
ctx->ctx_id = ctx_id;
+ ctx->last_flush_req = 0;
ctx->ctx_crm_intf = NULL;
ctx->crm_ctx_intf = crm_node_intf;
ctx->hw_mgr_intf = hw_mgr_intf;
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c
index d98b900bc07a..e5232c482a17 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -303,6 +303,12 @@ int32_t cam_context_config_dev_to_hw(
return rc;
}
+ if ((len < sizeof(struct cam_packet)) ||
+ (cmd->offset >= (len - sizeof(struct cam_packet)))) {
+ CAM_ERR(CAM_CTXT, "Not enough buf");
+ return -EINVAL;
+
+ }
packet = (struct cam_packet *) ((uint8_t *)packet_addr +
(uint32_t)cmd->offset);
@@ -333,6 +339,7 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
uintptr_t packet_addr;
struct cam_packet *packet;
size_t len = 0;
+ size_t remain_len = 0;
int32_t i = 0, j = 0;
if (!ctx || !cmd) {
@@ -381,11 +388,19 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
goto free_req;
}
+ remain_len = len;
+ if ((len < sizeof(struct cam_packet)) ||
+ ((size_t)cmd->offset >= len - sizeof(struct cam_packet))) {
+ CAM_ERR(CAM_CTXT, "invalid buff length: %zu or offset", len);
+ return -EINVAL;
+ }
+
+ remain_len -= (size_t)cmd->offset;
packet = (struct cam_packet *) ((uint8_t *)packet_addr +
(uint32_t)cmd->offset);
if (packet->header.request_id <= ctx->last_flush_req) {
- CAM_DBG(CAM_CORE,
+ CAM_ERR(CAM_CORE,
"request %lld has been flushed, reject packet",
packet->header.request_id);
rc = -EINVAL;
@@ -398,6 +413,7 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
/* preprocess the configuration */
memset(&cfg, 0, sizeof(cfg));
cfg.packet = packet;
+ cfg.remain_len = remain_len;
cfg.ctxt_to_hw_map = ctx->ctxt_to_hw_map;
cfg.max_hw_update_entries = CAM_CTX_CFG_MAX;
cfg.num_hw_update_entries = req->num_hw_update_entries;
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_core_defs.h b/drivers/media/platform/msm/camera_v3/cam_core/cam_core_defs.h
deleted file mode 100644
index 32330b1e07e4..000000000000
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_core_defs.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _CAM_CORE_DEFS_H_
-#define _CAM_CORE_DEFS_H_
-
-#define CAM_CORE_TRACE_ENABLE 0
-
-#if (CAM_CORE_TRACE_ENABLE == 1)
- #define CAM_CORE_DBG(fmt, args...) do { \
- trace_printk("%d: [cam_core_dbg] "fmt"\n", __LINE__, ##args); \
- pr_debug("%s:%d "fmt"\n", __func__, __LINE__, ##args); \
- } while (0)
-
- #define CAM_CORE_WARN(fmt, args...) do { \
- trace_printk("%d: [cam_core_warn] "fmt"\n", __LINE__, ##args); \
- pr_warn("%s:%d "fmt"\n", __func__, __LINE__, ##args); \
- } while (0)
-
- #define CAM_CORE_ERR(fmt, args...) do { \
- trace_printk("%d: [cam_core_err] "fmt"\n", __LINE__, ##args); \
- pr_err("%s:%d "fmt"\n", __func__, __LINE__, ##args);\
- } while (0)
-#else
- #define CAM_CORE_DBG(fmt, args...) pr_debug("%s:%d "fmt"\n", \
- __func__, __LINE__, ##args)
-
- #define CAM_CORE_WARN(fmt, args...) pr_warn("%s:%d "fmt"\n", \
- __func__, __LINE__, ##args)
-
- #define CAM_CORE_ERR(fmt, args...) pr_err("%s:%d "fmt"\n", \
- __func__, __LINE__, ##args)
-#endif
-
-#endif /* _CAM_CORE_DEFS_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h b/drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h
index fd30f115cc0c..c3d1c2eff4e9 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -153,6 +153,7 @@ struct cam_hw_mgr_dump_pf_data {
* struct cam_hw_prepare_update_args - Payload for prepare command
*
* @packet: CSL packet from user mode driver
+ * @remain_len Remaining length of CPU buffer after config offset
* @ctxt_to_hw_map: HW context from the acquire
* @max_hw_update_entries: Maximum hardware update entries supported
* @hw_update_entries: Actual hardware update configuration (returned)
@@ -169,6 +170,7 @@ struct cam_hw_mgr_dump_pf_data {
*/
struct cam_hw_prepare_update_args {
struct cam_packet *packet;
+ size_t remain_len;
void *ctxt_to_hw_map;
uint32_t max_hw_update_entries;
struct cam_hw_update_entry *hw_update_entries;
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c b/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c
index 9da340b1e766..ee9b2bfc1bfa 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -111,6 +111,7 @@ static int __cam_node_handle_acquire_dev(struct cam_node *node,
goto err;
}
+ ctx->last_flush_req = 0;
rc = cam_context_handle_acquire_dev(ctx, acquire);
if (rc) {
CAM_ERR(CAM_CORE, "Acquire device failed for node %s",
@@ -657,6 +658,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd)
"acquire device failed(rc = %d)", rc);
goto acquire_kfree;
}
+ CAM_INFO(CAM_CORE, "Acquire HW successful");
}
if (copy_to_user((void __user *)cmd->handle, acquire_ptr,
@@ -763,6 +765,8 @@ acquire_kfree:
"release device failed(rc = %d)", rc);
}
+ CAM_INFO(CAM_CORE, "Release HW done(rc = %d)", rc);
+
release_kfree:
kfree(release_ptr);
break;
diff --git a/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c b/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c
index 2a91f03ecdc8..017e810e07c0 100644
--- a/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c
+++ b/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -313,6 +313,9 @@ static int cam_cpas_util_axi_setup(struct cam_cpas *cpas_core,
goto mnoc_node_get_fail;
}
axi_port->axi_port_mnoc_node = axi_port_mnoc_node;
+ axi_port->ib_bw_voting_needed =
+ of_property_read_bool(axi_port_node,
+ "ib-bw-voting-needed");
rc = cam_cpas_util_register_bus_client(soc_info,
axi_port_mnoc_node, &axi_port->mnoc_bus);
@@ -662,12 +665,19 @@ static int cam_cpas_util_apply_client_axi_vote(
axi_port->camnoc_bus.src, axi_port->camnoc_bus.dst,
camnoc_bw, mnoc_bw);
- rc = cam_cpas_util_vote_bus_client_bw(&axi_port->mnoc_bus,
- mnoc_bw, mnoc_bw, false);
+ if (axi_port->ib_bw_voting_needed)
+ rc = cam_cpas_util_vote_bus_client_bw(&axi_port->mnoc_bus,
+ mnoc_bw, mnoc_bw, false);
+ else
+ rc = cam_cpas_util_vote_bus_client_bw(&axi_port->mnoc_bus,
+ mnoc_bw, 0, false);
+
if (rc) {
CAM_ERR(CAM_CPAS,
"Failed in mnoc vote ab[%llu] ib[%llu] rc=%d",
- mnoc_bw, mnoc_bw, rc);
+ mnoc_bw,
+ (axi_port->ib_bw_voting_needed ? mnoc_bw : 0),
+ rc);
goto unlock_axi_port;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.h b/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.h
index f93d036ecfcf..8e016191edb2 100644
--- a/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.h
+++ b/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -149,6 +149,7 @@ struct cam_cpas_bus_client {
* @camnoc_bus: CAMNOC bus client info for this port
* @mnoc_bus: MNOC bus client info for this port
* @axi_port_name: Name of this AXI port
+ * @ib_bw_voting_needed: if this port can update ib bw dynamically
* @axi_port_node: Node representing this AXI Port
* @axi_port_mnoc_node: Node representing mnoc in this AXI Port
* @axi_port_camnoc_node: Node representing camnoc in this AXI Port
@@ -161,6 +162,7 @@ struct cam_cpas_axi_port {
struct cam_cpas_bus_client camnoc_bus;
struct cam_cpas_bus_client mnoc_bus;
const char *axi_port_name;
+ bool ib_bw_voting_needed;
struct device_node *axi_port_node;
struct device_node *axi_port_mnoc_node;
struct device_node *axi_port_camnoc_node;
diff --git a/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c
index 8f89c4b7b5fd..49774f24ba20 100644
--- a/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c
+++ b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -20,9 +20,11 @@
#include "cam_io_util.h"
#include "cam_cpas_soc.h"
#include "cpastop100.h"
+#include "cpastop_v150_100.h"
#include "cpastop_v170_110.h"
#include "cpastop_v175_100.h"
#include "cpastop_v175_101.h"
+#include "cpastop_v175_120.h"
struct cam_camnoc_info *camnoc_info;
@@ -104,6 +106,17 @@ static int cam_cpastop_get_hw_info(struct cam_hw_info *cpas_hw,
(hw_caps->cpas_version.minor == 0) &&
(hw_caps->cpas_version.incr == 1))
soc_info->hw_version = CAM_CPAS_TITAN_175_V101;
+ else if ((hw_caps->cpas_version.major == 1) &&
+ (hw_caps->cpas_version.minor == 2) &&
+ (hw_caps->cpas_version.incr == 0))
+ soc_info->hw_version = CAM_CPAS_TITAN_175_V120;
+ } else if ((hw_caps->camera_version.major == 1) &&
+ (hw_caps->camera_version.minor == 5) &&
+ (hw_caps->camera_version.incr == 0)) {
+ if ((hw_caps->cpas_version.major == 1) &&
+ (hw_caps->cpas_version.minor == 0) &&
+ (hw_caps->cpas_version.incr == 0))
+ soc_info->hw_version = CAM_CPAS_TITAN_150_V100;
}
CAM_DBG(CAM_CPAS, "CPAS HW VERSION %x", soc_info->hw_version);
@@ -642,6 +655,12 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw,
case CAM_CPAS_TITAN_175_V101:
camnoc_info = &cam175_cpas101_camnoc_info;
break;
+ case CAM_CPAS_TITAN_175_V120:
+ camnoc_info = &cam175_cpas120_camnoc_info;
+ break;
+ case CAM_CPAS_TITAN_150_V100:
+ camnoc_info = &cam150_cpas100_camnoc_info;
+ break;
default:
CAM_ERR(CAM_CPAS, "Camera Version not supported %d.%d.%d",
hw_caps->camera_version.major,
diff --git a/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v150_100.h b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v150_100.h
new file mode 100644
index 000000000000..cf9f82d07b20
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v150_100.h
@@ -0,0 +1,537 @@
+/* Copyright (c) 2018, 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CPASTOP_V150_100_H_
+#define _CPASTOP_V150_100_H_
+
+#define TEST_IRQ_ENABLE 0
+
+static struct cam_camnoc_irq_sbm cam_cpas_v150_100_irq_sbm = {
+ .sbm_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2040, /* SBM_FAULTINEN0_LOW */
+ .value = 0x1 | /* SBM_FAULTINEN0_LOW_PORT0_MASK*/
+ 0x2 | /* SBM_FAULTINEN0_LOW_PORT1_MASK */
+ 0x4 | /* SBM_FAULTINEN0_LOW_PORT2_MASK */
+ 0x8 | /* SBM_FAULTINEN0_LOW_PORT3_MASK */
+ 0x10 | /* SBM_FAULTINEN0_LOW_PORT4_MASK */
+ 0x20 | /* SBM_FAULTINEN0_LOW_PORT5_MASK */
+ (TEST_IRQ_ENABLE ?
+ 0x100 : /* SBM_FAULTINEN0_LOW_PORT8_MASK */
+ 0x0),
+ },
+ .sbm_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2048, /* SBM_FAULTINSTATUS0_LOW */
+ },
+ .sbm_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x2080, /* SBM_FLAGOUTCLR0_LOW */
+ .value = TEST_IRQ_ENABLE ? 0x6 : 0x2,
+ }
+};
+
+static struct cam_camnoc_irq_err
+ cam_cpas_v150_100_irq_err[] = {
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR,
+ .enable = true,
+ .sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2708, /* ERRLOGGER_MAINCTL_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2710, /* ERRLOGGER_ERRVLD_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x2718, /* ERRLOGGER_ERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT1_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x5a0, /* SPECIFIC_IFE02_ENCERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x590, /* SPECIFIC_IFE02_ENCERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x598, /* SPECIFIC_IFE02_ENCERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IFE13_UBWC_ENCODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x4, /* SBM_FAULTINSTATUS0_LOW_PORT2_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x9a0, /* SPECIFIC_IFE13_ENCERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x990, /* SPECIFIC_IFE13_ENCERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x998, /* SPECIFIC_IFE13_ENCERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x8, /* SBM_FAULTINSTATUS0_LOW_PORT3_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0xd20, /* SPECIFIC_IBL_RD_DECERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0xd10, /* SPECIFIC_IBL_RD_DECERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0xd18, /* SPECIFIC_IBL_RD_DECERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_ENCODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x10, /* SBM_FAULTINSTATUS0_LOW_PORT4_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x11a0, /* SPECIFIC_IBL_WR_ENCERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x1190,
+ /* SPECIFIC_IBL_WR_ENCERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x1198, /* SPECIFIC_IBL_WR_ENCERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT,
+ .enable = true,
+ .sbm_port = 0x20, /* SBM_FAULTINSTATUS0_LOW_PORT5_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2088, /* SBM_FLAGOUTSET0_LOW */
+ .value = 0x1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2090, /* SBM_FLAGOUTSTATUS0_LOW */
+ },
+ .err_clear = {
+ .enable = false,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_RESERVED1,
+ .enable = false,
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_RESERVED2,
+ .enable = false,
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_CAMNOC_TEST,
+ .enable = TEST_IRQ_ENABLE ? true : false,
+ .sbm_port = 0x100, /* SBM_FAULTINSTATUS0_LOW_PORT8_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2088, /* SBM_FLAGOUTSET0_LOW */
+ .value = 0x5,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2090, /* SBM_FLAGOUTSTATUS0_LOW */
+ },
+ .err_clear = {
+ .enable = false,
+ },
+ },
+};
+
+static struct cam_camnoc_specific
+ cam_cpas_v150_100_camnoc_specific[] = {
+ {
+ .port_type = CAM_CAMNOC_CDM,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x30, /* SPECIFIC_CDM_PRIORITYLUT_LOW */
+ .value = 0x22222222,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x34, /* SPECIFIC_CDM_PRIORITYLUT_HIGH */
+ .value = 0x22222222,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x38, /* SPECIFIC_CDM_URGENCY_LOW */
+ .mask = 0x7, /* SPECIFIC_CDM_URGENCY_LOW_READ_MASK */
+ .shift = 0x0, /* SPECIFIC_CDM_URGENCY_LOW_READ_SHIFT */
+ .value = 0x2,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x40, /* SPECIFIC_CDM_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x48, /* SPECIFIC_CDM_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IFE02,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x430, /* SPECIFIC_IFE02_PRIORITYLUT_LOW */
+ .value = 0x66665433,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x434, /* SPECIFIC_IFE02_PRIORITYLUT_HIGH */
+ .value = 0x66666666,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x438, /* SPECIFIC_IFE02_URGENCY_LOW */
+ /* SPECIFIC_IFE02_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IFE02_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x440, /* SPECIFIC_IFE02_DANGERLUT_LOW */
+ .value = 0xFFFFFF00,
+ },
+ .safe_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x448, /* SPECIFIC_IFE02_SAFELUT_LOW */
+ .value = 0x1,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IFE13,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x830, /* SPECIFIC_IFE13_PRIORITYLUT_LOW */
+ .value = 0x66665433,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x834, /* SPECIFIC_IFE13_PRIORITYLUT_HIGH */
+ .value = 0x66666666,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x838, /* SPECIFIC_IFE13_URGENCY_LOW */
+ /* SPECIFIC_IFE13_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IFE13_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x840, /* SPECIFIC_IFE13_DANGERLUT_LOW */
+ .value = 0xFFFFFF00,
+ },
+ .safe_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x848, /* SPECIFIC_IFE13_SAFELUT_LOW */
+ .value = 0x1,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IPE_BPS_LRME_READ,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0xc30, /* SPECIFIC_IBL_RD_PRIORITYLUT_LOW */
+ .value = 0x33333333,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0xc34, /* SPECIFIC_IBL_RD_PRIORITYLUT_HIGH */
+ .value = 0x33333333,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0xc38, /* SPECIFIC_IBL_RD_URGENCY_LOW */
+ /* SPECIFIC_IBL_RD_URGENCY_LOW_READ_MASK */
+ .mask = 0x7,
+ /* SPECIFIC_IBL_RD_URGENCY_LOW_READ_SHIFT */
+ .shift = 0x0,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0xc40, /* SPECIFIC_IBL_RD_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0xc48, /* SPECIFIC_IBL_RD_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0xd08, /* SPECIFIC_IBL_RD_DECCTL_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IPE_BPS_LRME_WRITE,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1030, /* SPECIFIC_IBL_WR_PRIORITYLUT_LOW */
+ .value = 0x33333333,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1034, /* SPECIFIC_IBL_WR_PRIORITYLUT_HIGH */
+ .value = 0x33333333,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x1038, /* SPECIFIC_IBL_WR_URGENCY_LOW */
+ /* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1040, /* SPECIFIC_IBL_WR_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1048, /* SPECIFIC_IBL_WR_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1188, /* SPECIFIC_IBL_WR_ENCCTL_LOW */
+ .value = 0x5,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_JPEG,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1430, /* SPECIFIC_JPEG_PRIORITYLUT_LOW */
+ .value = 0x22222222,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1434, /* SPECIFIC_JPEG_PRIORITYLUT_HIGH */
+ .value = 0x22222222,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1438, /* SPECIFIC_JPEG_URGENCY_LOW */
+ .value = 0x22,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1440, /* SPECIFIC_JPEG_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1448, /* SPECIFIC_JPEG_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_FD,
+ .enable = false,
+ },
+ {
+ .port_type = CAM_CAMNOC_ICP,
+ .enable = true,
+ .flag_out_set0_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_WRITE,
+ .masked_value = 0,
+ .offset = 0x2088,
+ .value = 0x100000,
+ },
+ },
+};
+
+static struct cam_camnoc_err_logger_info cam150_cpas100_err_logger_offsets = {
+ .mainctrl = 0x2708, /* ERRLOGGER_MAINCTL_LOW */
+ .errvld = 0x2710, /* ERRLOGGER_ERRVLD_LOW */
+ .errlog0_low = 0x2720, /* ERRLOGGER_ERRLOG0_LOW */
+ .errlog0_high = 0x2724, /* ERRLOGGER_ERRLOG0_HIGH */
+ .errlog1_low = 0x2728, /* ERRLOGGER_ERRLOG1_LOW */
+ .errlog1_high = 0x272c, /* ERRLOGGER_ERRLOG1_HIGH */
+ .errlog2_low = 0x2730, /* ERRLOGGER_ERRLOG2_LOW */
+ .errlog2_high = 0x2734, /* ERRLOGGER_ERRLOG2_HIGH */
+ .errlog3_low = 0x2738, /* ERRLOGGER_ERRLOG3_LOW */
+ .errlog3_high = 0x273c, /* ERRLOGGER_ERRLOG3_HIGH */
+};
+
+static struct cam_cpas_hw_errata_wa_list cam150_cpas100_errata_wa_list = {
+ .camnoc_flush_slave_pending_trans = {
+ .enable = false,
+ .data.reg_info = {
+ .access_type = CAM_REG_TYPE_READ,
+ .offset = 0x2100, /* SidebandManager_SenseIn0_Low */
+ .mask = 0xE0000, /* Bits 17, 18, 19 */
+ .value = 0, /* expected to be 0 */
+ },
+ },
+};
+
+static struct cam_camnoc_info cam150_cpas100_camnoc_info = {
+ .specific = &cam_cpas_v150_100_camnoc_specific[0],
+ .specific_size = sizeof(cam_cpas_v150_100_camnoc_specific) /
+ sizeof(cam_cpas_v150_100_camnoc_specific[0]),
+ .irq_sbm = &cam_cpas_v150_100_irq_sbm,
+ .irq_err = &cam_cpas_v150_100_irq_err[0],
+ .irq_err_size = sizeof(cam_cpas_v150_100_irq_err) /
+ sizeof(cam_cpas_v150_100_irq_err[0]),
+ .err_logger = &cam150_cpas100_err_logger_offsets,
+ .errata_wa_list = &cam150_cpas100_errata_wa_list,
+};
+
+#endif /* _CPASTOP_V150_100_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v175_120.h b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v175_120.h
new file mode 100644
index 000000000000..7212bb30940a
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v175_120.h
@@ -0,0 +1,769 @@
+/* Copyright (c) 2018, 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CPASTOP_V175_120_H_
+#define _CPASTOP_V175_120_H_
+
+#define TEST_IRQ_ENABLE 0
+
+static struct cam_camnoc_irq_sbm cam_cpas_v175_120_irq_sbm = {
+ .sbm_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2240, /* SBM_FAULTINEN0_LOW */
+ .value = 0x1 | /* SBM_FAULTINEN0_LOW_PORT0_MASK*/
+ 0x2 | /* SBM_FAULTINEN0_LOW_PORT1_MASK */
+ 0x4 | /* SBM_FAULTINEN0_LOW_PORT2_MASK */
+ 0x8 | /* SBM_FAULTINEN0_LOW_PORT3_MASK */
+ 0x10 | /* SBM_FAULTINEN0_LOW_PORT4_MASK */
+ 0x20 | /* SBM_FAULTINEN0_LOW_PORT5_MASK */
+ (TEST_IRQ_ENABLE ?
+ 0x100 : /* SBM_FAULTINEN0_LOW_PORT8_MASK */
+ 0x0),
+ },
+ .sbm_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2248, /* SBM_FAULTINSTATUS0_LOW */
+ },
+ .sbm_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x2280, /* SBM_FLAGOUTCLR0_LOW */
+ .value = TEST_IRQ_ENABLE ? 0x6 : 0x2,
+ }
+};
+
+static struct cam_camnoc_irq_err
+ cam_cpas_v175_120_irq_err[] = {
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR,
+ .enable = true,
+ .sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x4F08, /* ERRORLOGGER_MAINCTL_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x4F10, /* ERRORLOGGER_ERRVLD_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x4F18, /* ERRORLOGGER_ERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IFE0_UBWC_ENCODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT1_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x3BA0, /* SPECIFIC_IFE02_ENCERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x3B90, /* SPECIFIC_IFE02_ENCERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x3B98, /* SPECIFIC_IFE02_ENCERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IFE1_WRITE_UBWC_ENCODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x4, /* SBM_FAULTINSTATUS0_LOW_PORT2_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x55a0, /* SPECIFIC_IFE13_ENCERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x5590, /* SPECIFIC_IFE13_ENCERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x5598, /* SPECIFIC_IFE13_ENCERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x8, /* SBM_FAULTINSTATUS0_LOW_PORT3_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2F20, /* SPECIFIC_IBL_RD_DECERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2F10, /* SPECIFIC_IBL_RD_DECERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x2F18, /* SPECIFIC_IBL_RD_DECERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_ENCODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x10, /* SBM_FAULTINSTATUS0_LOW_PORT4_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2Ba0, /* SPECIFIC_IBL_WR_ENCERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2B90,
+ /* SPECIFIC_IBL_WR_ENCERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x2B98, /* SPECIFIC_IBL_WR_ENCERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT,
+ .enable = true,
+ .sbm_port = 0x20, /* SBM_FAULTINSTATUS0_LOW_PORT5_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2288, /* SBM_FLAGOUTSET0_LOW */
+ .value = 0x1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2290, /* SBM_FLAGOUTSTATUS0_LOW */
+ },
+ .err_clear = {
+ .enable = false,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_RESERVED1,
+ .enable = false,
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_RESERVED2,
+ .enable = false,
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_CAMNOC_TEST,
+ .enable = TEST_IRQ_ENABLE ? true : false,
+ .sbm_port = 0x100, /* SBM_FAULTINSTATUS0_LOW_PORT8_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2288, /* SBM_FLAGOUTSET0_LOW */
+ .value = 0x5,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2290, /* SBM_FLAGOUTSTATUS0_LOW */
+ },
+ .err_clear = {
+ .enable = false,
+ },
+ },
+};
+
+static struct cam_camnoc_specific
+ cam_cpas_v175_120_camnoc_specific[] = {
+ {
+ .port_type = CAM_CAMNOC_CDM,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x4230, /* SPECIFIC_CDM_PRIORITYLUT_LOW */
+ .value = 0x22222222,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x4234, /* SPECIFIC_CDM_PRIORITYLUT_HIGH */
+ .value = 0x22222222,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ /* cdm_main_SpecificToNttpTr_Urgency_Low */
+ .offset = 0x4238,
+ .mask = 0x7, /* SPECIFIC_CDM_URGENCY_LOW_READ_MASK */
+ .shift = 0x0, /* SPECIFIC_CDM_URGENCY_LOW_READ_SHIFT */
+ .value = 0x2,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x4240, /* SPECIFIC_CDM_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x4248, /* SPECIFIC_CDM_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IFE0123_RDI_WRITE,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ /* SPECIFIC_IFE0123_PRIORITYLUT_LOW */
+ .offset = 0x3630,
+ .value = 0x66665433,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ /* SPECIFIC_IFE0123_PRIORITYLUT_HIGH */
+ .offset = 0x3634,
+ .value = 0x66666666,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x3638, /* SPECIFIC_IFE0123_URGENCY_LOW */
+ /* SPECIFIC_IFE0123_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IFE0123_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x3640, /* SPECIFIC_IFE0123_DANGERLUT_LOW */
+ .value = 0xFFFFFF00,
+ },
+ .safe_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x3648, /* SPECIFIC_IFE0123_SAFELUT_LOW */
+ .value = 0xF,
+ },
+ .ubwc_ctl = {
+ /*
+ * Do not explicitly set ubwc config register.
+ * Power on default values are taking care of required
+ * register settings.
+ */
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IFE0_NRDI_WRITE,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3A30, /* SPECIFIC_IFE0_PRIORITYLUT_LOW */
+ .value = 0x66665433,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3A34, /* SPECIFIC_IFE0_PRIORITYLUT_HIGH */
+ .value = 0x66666666,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x3A38, /* SPECIFIC_IFE0_URGENCY_LOW */
+ /* SPECIFIC_IFE0_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IFE0_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x3A40, /* SPECIFIC_IFE0_DANGERLUT_LOW */
+ .value = 0xFFFFFF00,
+ },
+ .safe_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x3A48, /* SPECIFIC_IFE0_SAFELUT_LOW */
+ .value = 0xF,
+ },
+ .ubwc_ctl = {
+ /*
+ * Do not explicitly set ubwc config register.
+ * Power on default values are taking care of required
+ * register settings.
+ */
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3B88, /* SPECIFIC_IFE0_ENCCTL_LOW */
+ .value = 1,
+ },
+ },
+ {
+ /* IFE0/1 RDI READ PATH */
+ .port_type = CAM_CAMNOC_IFE01_RDI_READ,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3230, /* SPECIFIC_IFE1_PRIORITYLUT_LOW */
+ .value = 0x44443333,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3234, /* SPECIFIC_IFE1_PRIORITYLUT_HIGH */
+ .value = 0x66665555,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x3238, /* SPECIFIC_IFE1_URGENCY_LOW */
+ /* SPECIFIC_IFE1_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x7,
+ /* SPECIFIC_IFE1_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x0,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x3240, /* SPECIFIC_IFE1_DANGERLUT_LOW */
+ .value = 0x00000000,
+ },
+ .safe_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x3248, /* SPECIFIC_IFE1_SAFELUT_LOW */
+ .value = 0xF,
+ },
+ .ubwc_ctl = {
+ /*
+ * Do not explicitly set ubwc config register.
+ * Power on default values are taking care of required
+ * register settings.
+ */
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IFE1_NRDI_WRITE,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x5430, /* SPECIFIC_IFE1_WR_PRIORITYLUT_LOW */
+ .value = 0x66665433,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ /* SPECIFIC_IFE1_WR_PRIORITYLUT_HIGH */
+ .offset = 0x5434,
+ .value = 0x66666666,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x5438, /* SPECIFIC_IFE1_WR_URGENCY_LOW */
+ /* SPECIFIC_IFE1_WR_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IFE1_WR_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x5440, /* SPECIFIC_IFE1_WR_DANGERLUT_LOW */
+ .value = 0xFFFFFF00,
+ },
+ .safe_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x5448, /* SPECIFIC_IFE1_WR_SAFELUT_LOW */
+ .value = 0xF,
+ },
+ .ubwc_ctl = {
+ /*
+ * Do not explicitly set ubwc config register.
+ * Power on default values are taking care of required
+ * register settings.
+ */
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x5588, /* SPECIFIC_IFE1_WR_ENCCTL_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IPE_BPS_LRME_READ,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2E30, /* SPECIFIC_IBL_RD_PRIORITYLUT_LOW */
+ .value = 0x33333333,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2E34, /* SPECIFIC_IBL_RD_PRIORITYLUT_HIGH */
+ .value = 0x33333333,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x2E38, /* SPECIFIC_IBL_RD_URGENCY_LOW */
+ /* SPECIFIC_IBL_RD_URGENCY_LOW_READ_MASK */
+ .mask = 0x7,
+ /* SPECIFIC_IBL_RD_URGENCY_LOW_READ_SHIFT */
+ .shift = 0x0,
+ .value = 0x3,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2E40, /* SPECIFIC_IBL_RD_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2E48, /* SPECIFIC_IBL_RD_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ /*
+ * Do not explicitly set ubwc config register.
+ * Power on default values are taking care of required
+ * register settings.
+ */
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2F08, /* SPECIFIC_IBL_RD_DECCTL_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IPE_BPS_LRME_WRITE,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2A30, /* SPECIFIC_IBL_WR_PRIORITYLUT_LOW */
+ .value = 0x33333333,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2A34, /* SPECIFIC_IBL_WR_PRIORITYLUT_HIGH */
+ .value = 0x33333333,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x2A38, /* SPECIFIC_IBL_WR_URGENCY_LOW */
+ /* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 0x3,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2A40, /* SPECIFIC_IBL_WR_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2A48, /* SPECIFIC_IBL_WR_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ /*
+ * Do not explicitly set ubwc config register.
+ * Power on default values are taking care of required
+ * register settings.
+ */
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2B88, /* SPECIFIC_IBL_WR_ENCCTL_LOW */
+ .value = 0,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IPE_VID_DISP_WRITE,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ /* SPECIFIC_IPE_VID_DISP_PRIORITYLUT_LOW */
+ .offset = 0x5E30,
+ .value = 0x33333333,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ /* SPECIFIC_IPE_VID_DISP_PRIORITYLUT_HIGH */
+ .offset = 0x5E34,
+ .value = 0x33333333,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ /* SPECIFIC_IPE_VID_DISP_URGENCY_LOW */
+ .offset = 0x5E38,
+ /* SPECIFIC_IPE_VID_DISP_URGENCY_LOW_READ_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IPE_VID_DISP_URGENCY_LOW_READ_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ /* SPECIFIC__IPE_VID_DISP_DANGERLUT_LOW */
+ .offset = 0x5E40,
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ /* SPECIFIC_IPE_VID_DISP_SAFELUT_LOW */
+ .offset = 0x5E48,
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ /*
+ * Do not explicitly set ubwc config register.
+ * Power on default values are taking care of required
+ * register settings.
+ */
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x5F88, /* SPECIFIC_IBL_WR_ENCCTL_LOW */
+ .value = 1,
+ },
+ },
+
+ {
+ .port_type = CAM_CAMNOC_JPEG,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2630, /* SPECIFIC_JPEG_PRIORITYLUT_LOW */
+ .value = 0x22222222,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2634, /* SPECIFIC_JPEG_PRIORITYLUT_HIGH */
+ .value = 0x22222222,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2638, /* SPECIFIC_JPEG_URGENCY_LOW */
+ .value = 0x22,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2640, /* SPECIFIC_JPEG_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2648, /* SPECIFIC_JPEG_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_FD,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3E30, /* SPECIFIC_FD_PRIORITYLUT_LOW */
+ .value = 0x44444444,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3E34, /* SPECIFIC_FD_PRIORITYLUT_HIGH */
+ .value = 0x44444444,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3E38, /* SPECIFIC_FD_URGENCY_LOW */
+ .value = 0x44,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3E40, /* SPECIFIC_FD_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3E48, /* SPECIFIC_FD_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ },
+
+ },
+ {
+ /*SidebandManager_main_SidebandManager_FlagOutSet0_Low*/
+ .port_type = CAM_CAMNOC_ICP,
+ .enable = true,
+ .flag_out_set0_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_WRITE,
+ .masked_value = 0,
+ .offset = 0x2288,
+ .value = 0x100000,
+ },
+ },
+};
+
+static struct cam_camnoc_err_logger_info cam175_cpas120_err_logger_offsets = {
+ .mainctrl = 0x4F08, /* ERRLOGGER_MAINCTL_LOW */
+ .errvld = 0x4F10, /* ERRLOGGER_ERRVLD_LOW */
+ .errlog0_low = 0x4F20, /* ERRLOGGER_ERRLOG0_LOW */
+ .errlog0_high = 0x4F24, /* ERRLOGGER_ERRLOG0_HIGH */
+ .errlog1_low = 0x4F28, /* ERRLOGGER_ERRLOG1_LOW */
+ .errlog1_high = 0x4F2c, /* ERRLOGGER_ERRLOG1_HIGH */
+ .errlog2_low = 0x4F30, /* ERRLOGGER_ERRLOG2_LOW */
+ .errlog2_high = 0x4F34, /* ERRLOGGER_ERRLOG2_HIGH */
+ .errlog3_low = 0x4F38, /* ERRLOGGER_ERRLOG3_LOW */
+ .errlog3_high = 0x4F3c, /* ERRLOGGER_ERRLOG3_HIGH */
+};
+
+static struct cam_cpas_hw_errata_wa_list cam175_cpas120_errata_wa_list = {
+ .camnoc_flush_slave_pending_trans = {
+ .enable = false,
+ .data.reg_info = {
+ .access_type = CAM_REG_TYPE_READ,
+ .offset = 0x2300, /* SidebandManager_SenseIn0_Low */
+ .mask = 0xE0000, /* Bits 17, 18, 19 */
+ .value = 0, /* expected to be 0 */
+ },
+ },
+};
+
+static struct cam_camnoc_info cam175_cpas120_camnoc_info = {
+ .specific = &cam_cpas_v175_120_camnoc_specific[0],
+ .specific_size = sizeof(cam_cpas_v175_120_camnoc_specific) /
+ sizeof(cam_cpas_v175_120_camnoc_specific[0]),
+ .irq_sbm = &cam_cpas_v175_120_irq_sbm,
+ .irq_err = &cam_cpas_v175_120_irq_err[0],
+ .irq_err_size = sizeof(cam_cpas_v175_120_irq_err) /
+ sizeof(cam_cpas_v175_120_irq_err[0]),
+ .err_logger = &cam175_cpas120_err_logger_offsets,
+ .errata_wa_list = &cam175_cpas120_errata_wa_list,
+};
+
+#endif /* _CPASTOP_V175_120_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_fd/Makefile b/drivers/media/platform/msm/camera_v3/cam_fd/Makefile
index ed896e511963..2e4511d2b48f 100644
--- a/drivers/media/platform/msm/camera_v3/cam_fd/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_fd/Makefile
@@ -7,7 +7,7 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cdm
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw
-ccflags-y += -Idrivers/media/platform/msm/camera
+ccflags-y += -Idrivers/media/platform/msm/camera_v3
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cpas/include
obj-$(CONFIG_SPECTRA_CAMERA) += fd_hw_mgr/
diff --git a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/Makefile b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/Makefile
index d6e76d18e799..61c255e75158 100644
--- a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/Makefile
@@ -7,7 +7,7 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cdm
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw
-ccflags-y += -Idrivers/media/platform/msm/camera
+ccflags-y += -Idrivers/media/platform/msm/camera_v3
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cpas/include
obj-$(CONFIG_SPECTRA_CAMERA) += fd_hw/
diff --git a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
index ec0a906cb99a..8403d4dbe533 100644
--- a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -30,7 +30,8 @@
static struct cam_fd_hw_mgr g_fd_hw_mgr;
-static int cam_fd_mgr_util_packet_validate(struct cam_packet *packet)
+static int cam_fd_mgr_util_packet_validate(struct cam_packet *packet,
+ size_t remain_len)
{
struct cam_cmd_buf_desc *cmd_desc = NULL;
int i, rc;
@@ -50,7 +51,7 @@ static int cam_fd_mgr_util_packet_validate(struct cam_packet *packet)
packet->patch_offset, packet->num_patches,
packet->kmd_cmd_buf_offset, packet->kmd_cmd_buf_index);
- if (cam_packet_util_validate_packet(packet)) {
+ if (cam_packet_util_validate_packet(packet, remain_len)) {
CAM_ERR(CAM_FD, "invalid packet:%d %d %d %d %d",
packet->kmd_cmd_buf_index,
packet->num_cmd_buf, packet->cmd_buf_offset,
@@ -162,8 +163,10 @@ static int cam_fd_mgr_util_put_frame_req(
mutex_lock(&g_fd_hw_mgr.frame_req_mutex);
req_ptr = *frame_req;
- if (req_ptr)
+ if (req_ptr) {
+ list_del_init(&req_ptr->list);
list_add_tail(&req_ptr->list, src_list);
+ }
*frame_req = NULL;
mutex_unlock(&g_fd_hw_mgr.frame_req_mutex);
@@ -608,7 +611,13 @@ static int cam_fd_mgr_util_prepare_io_buf_info(int32_t iommu_hdl,
rc);
return rc;
}
-
+ if (io_cfg[i].offsets[plane] >= size) {
+ CAM_ERR(CAM_FD,
+ "Invalid cpu buf %d %d %d",
+ io_cfg[i].direction,
+ io_cfg[i].resource_type, plane);
+ return -EINVAL;
+ }
cpu_addr[plane] += io_cfg[i].offsets[plane];
}
@@ -1444,6 +1453,16 @@ unlock_dev_flush_ctx:
for (i = 0; i < flush_args->num_req_pending; i++) {
flush_req = (struct cam_fd_mgr_frame_request *)
flush_args->flush_req_pending[i];
+ CAM_DBG(CAM_FD, "flush pending req %llu",
+ flush_req->request_id);
+ cam_fd_mgr_util_put_frame_req(&hw_mgr->frame_free_list,
+ &flush_req);
+ }
+
+ for (i = 0; i < flush_args->num_req_active; i++) {
+ flush_req = (struct cam_fd_mgr_frame_request *)
+ flush_args->flush_req_active[i];
+ CAM_DBG(CAM_FD, "flush active req %llu", flush_req->request_id);
cam_fd_mgr_util_put_frame_req(&hw_mgr->frame_free_list,
&flush_req);
}
@@ -1559,7 +1578,8 @@ static int cam_fd_mgr_hw_prepare_update(void *hw_mgr_priv,
goto error;
}
- rc = cam_fd_mgr_util_packet_validate(prepare->packet);
+ rc = cam_fd_mgr_util_packet_validate(prepare->packet,
+ prepare->remain_len);
if (rc) {
CAM_ERR(CAM_FD, "Error in packet validation %d", rc);
goto error;
diff --git a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/Makefile b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/Makefile
index 7fe5a4067d02..389ca4c66b8d 100644
--- a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/Makefile
@@ -7,7 +7,7 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cdm
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw
-ccflags-y += -Idrivers/media/platform/msm/camera
+ccflags-y += -Idrivers/media/platform/msm/camera_v3
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cpas/include
obj-$(CONFIG_SPECTRA_CAMERA) += cam_fd_hw_dev.o cam_fd_hw_core.o cam_fd_hw_soc.o
diff --git a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
index 12d3c6bf1060..4084c43c2902 100644
--- a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -427,6 +427,7 @@ static int cam_fd_hw_util_processcmd_frame_done(struct cam_hw_info *fd_hw,
unsigned long flags;
int i;
+ mutex_lock(&fd_hw->hw_mutex);
spin_lock_irqsave(&fd_core->spin_lock, flags);
if ((fd_core->core_state != CAM_FD_CORE_STATE_IDLE) ||
(fd_core->results_valid == false) ||
@@ -436,6 +437,7 @@ static int cam_fd_hw_util_processcmd_frame_done(struct cam_hw_info *fd_hw,
fd_core->core_state, fd_core->results_valid,
fd_core->hw_req_private);
spin_unlock_irqrestore(&fd_core->spin_lock, flags);
+ mutex_unlock(&fd_hw->hw_mutex);
return -EINVAL;
}
fd_core->core_state = CAM_FD_CORE_STATE_READING_RESULTS;
@@ -516,6 +518,7 @@ static int cam_fd_hw_util_processcmd_frame_done(struct cam_hw_info *fd_hw,
fd_core->hw_req_private = NULL;
fd_core->core_state = CAM_FD_CORE_STATE_IDLE;
spin_unlock_irqrestore(&fd_core->spin_lock, flags);
+ mutex_unlock(&fd_hw->hw_mutex);
return 0;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
index c7ef37c65659..d4c9326ed5ab 100644
--- a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -206,6 +206,10 @@ static const struct of_device_id cam_fd_hw_dt_match[] = {
.compatible = "qcom,fd501",
.data = &cam_fd_wrapper200_core501_info,
},
+ {
+ .compatible = "qcom,fd501",
+ .data = &cam_fd_wrapper200_core501_info,
+ },
{}
};
MODULE_DEVICE_TABLE(of, cam_fd_hw_dt_match);
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_session_defs.h b/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_session_defs.h
index 38137b89295e..9f81c9c7feb0 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_session_defs.h
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_session_defs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -472,7 +472,6 @@ struct ica_stab_params {
struct frame_set {
struct frame_buffer buffers[IPE_IO_IMAGES_MAX];
- struct ica_stab_params ica_params;
uint32_t cdm_ica1_addr;
uint32_t cdm_ica2_addr;
} __packed;
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/hfi.c b/drivers/media/platform/msm/camera_v3/cam_icp/hfi.c
index da1bf9e52ce8..bf80938985f1 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/hfi.c
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/hfi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -42,6 +42,9 @@
#define HFI_MAX_POLL_TRY 5
+#define HFI_MAX_PC_POLL_TRY 150
+#define HFI_POLL_TRY_SLEEP 2
+
static struct hfi_info *g_hfi;
unsigned int g_icp_mmu_hdl;
static DEFINE_MUTEX(hfi_cmd_q_mutex);
@@ -513,8 +516,8 @@ void cam_hfi_disable_cpu(void __iomem *icp_base)
uint32_t val;
uint32_t try = 0;
- while (try < HFI_MAX_POLL_TRY) {
- data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS);
+ while (try < HFI_MAX_PC_POLL_TRY) {
+ data = cam_io_r_mb(icp_base + HFI_REG_A5_CSR_A5_STATUS);
CAM_DBG(CAM_HFI, "wfi status = %x\n", (int)data);
if (data & ICP_CSR_A5_STATUS_WFI)
@@ -523,7 +526,7 @@ void cam_hfi_disable_cpu(void __iomem *icp_base)
* and Host can the proceed. No interrupt is expected from FW
* at this time.
*/
- msleep(100);
+ msleep_interruptible(HFI_POLL_TRY_SLEEP);
try++;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/bps_hw/bps_core.c
index b969c92ccbc8..a330cff293d6 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/bps_hw/bps_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/bps_hw/bps_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -226,6 +226,13 @@ static int cam_bps_cmd_reset(struct cam_hw_soc_info *soc_info,
bool reset_bps_top_fail = false;
CAM_DBG(CAM_ICP, "CAM_ICP_BPS_CMD_RESET");
+
+ if (!core_info->clk_enable || !core_info->cpas_start) {
+ CAM_ERR(CAM_ICP, "BPS reset failed. clk_en %d cpas_start %d",
+ core_info->clk_enable, core_info->cpas_start);
+ return -EINVAL;
+ }
+
/* Reset BPS CDM core*/
cam_io_w_mb((uint32_t)0xF,
soc_info->reg_map[0].mem_base + BPS_CDM_RST_CMD);
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index 73e42de3fa03..0f103b92ba70 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -62,6 +62,8 @@
static struct cam_icp_hw_mgr icp_hw_mgr;
+static void cam_icp_mgr_process_dbg_buf(unsigned int debug_lvl);
+
static int cam_icp_send_ubwc_cfg(struct cam_icp_hw_mgr *hw_mgr)
{
struct cam_hw_intf *a5_dev_intf = NULL;
@@ -1834,12 +1836,13 @@ static int cam_icp_mgr_process_fatal_error(
if (event_notify->event_id == HFI_EVENT_SYS_ERROR) {
CAM_INFO(CAM_ICP, "received HFI_EVENT_SYS_ERROR");
rc = cam_icp_mgr_trigger_recovery(hw_mgr);
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
}
return rc;
}
-static void cam_icp_mgr_process_dbg_buf(void)
+static void cam_icp_mgr_process_dbg_buf(unsigned int debug_lvl)
{
uint32_t *msg_ptr = NULL, *pkt_ptr = NULL;
struct hfi_msg_debug *dbg_msg;
@@ -1861,6 +1864,8 @@ static void cam_icp_mgr_process_dbg_buf(void)
timestamp = ((((uint64_t)(dbg_msg->timestamp_hi) << 32)
| dbg_msg->timestamp_lo) >> 16);
trace_cam_icp_fw_dbg(dbg_buf, timestamp/2);
+ if (!debug_lvl)
+ CAM_INFO(CAM_ICP, "FW_DBG:%s", dbg_buf);
}
size_processed += (pkt_ptr[ICP_PACKET_SIZE] >>
BYTE_WORD_SHIFT);
@@ -1986,9 +1991,7 @@ static int32_t cam_icp_mgr_process_msg(void *priv, void *data)
}
}
- if (icp_hw_mgr.a5_debug_type ==
- HFI_DEBUG_MODE_QUEUE)
- cam_icp_mgr_process_dbg_buf();
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
if ((task_data->irq_status & A5_WDT_0) ||
(task_data->irq_status & A5_WDT_1)) {
@@ -2508,6 +2511,7 @@ static int cam_icp_mgr_abort_handle(
if (!rem_jiffies) {
rc = -ETIMEDOUT;
CAM_ERR(CAM_ICP, "FW timeout/err in abort handle command");
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
cam_hfi_queue_dump();
}
@@ -2562,9 +2566,7 @@ static int cam_icp_mgr_destroy_handle(
rc = -ETIMEDOUT;
CAM_ERR(CAM_ICP, "FW response timeout: %d for %u",
rc, ctx_data->ctx_id);
- if (icp_hw_mgr.a5_debug_type ==
- HFI_DEBUG_MODE_QUEUE)
- cam_icp_mgr_process_dbg_buf();
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
cam_hfi_queue_dump();
}
kfree(destroy_cmd);
@@ -2871,6 +2873,7 @@ static int cam_icp_mgr_send_fw_init(struct cam_icp_hw_mgr *hw_mgr)
if (!rem_jiffies) {
rc = -ETIMEDOUT;
CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
cam_hfi_queue_dump();
}
CAM_DBG(CAM_ICP, "Done Waiting for INIT DONE Message");
@@ -3122,6 +3125,7 @@ static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data,
if (!rem_jiffies) {
rc = -ETIMEDOUT;
CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
cam_hfi_queue_dump();
}
@@ -3377,7 +3381,7 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr,
}
if (!cpu_addr) {
- CAM_ERR(CAM_ICP, "Invalid cpu addr");
+ CAM_ERR(CAM_ICP, "invalid number of cmd buf");
return -EINVAL;
}
@@ -3847,9 +3851,12 @@ static void cam_icp_mgr_print_io_bufs(struct cam_packet *packet,
}
CAM_INFO(CAM_ICP,
- "pln %d w %d h %d size %d addr 0x%x offset 0x%x memh %x",
- j, io_cfg[i].planes[j].width,
+ "pln %d dir %d w %d h %d s %u sh %u sz %d addr 0x%x off 0x%x memh %x",
+ j, io_cfg[i].direction,
+ io_cfg[i].planes[j].width,
io_cfg[i].planes[j].height,
+ io_cfg[i].planes[j].plane_stride,
+ io_cfg[i].planes[j].slice_height,
(int32_t)src_buf_size,
(unsigned int)iova_addr,
io_cfg[i].offsets[j],
@@ -3936,6 +3943,9 @@ static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv,
packet = prepare_args->packet;
+ if (cam_packet_util_validate_packet(packet, prepare_args->remain_len))
+ return -EINVAL;
+
rc = cam_icp_mgr_pkt_validation(packet);
if (rc) {
mutex_unlock(&ctx_data->ctx_mutex);
@@ -4300,6 +4310,7 @@ static int cam_icp_mgr_create_handle(uint32_t dev_type,
if (!rem_jiffies) {
rc = -ETIMEDOUT;
CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
cam_hfi_queue_dump();
}
@@ -4346,6 +4357,7 @@ static int cam_icp_mgr_send_ping(struct cam_icp_hw_ctx_data *ctx_data)
if (!rem_jiffies) {
rc = -ETIMEDOUT;
CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
cam_hfi_queue_dump();
}
@@ -4619,6 +4631,7 @@ get_io_buf_failed:
hw_mgr->ctx_data[ctx_id].icp_dev_acquire_info = NULL;
acquire_info_failed:
cam_icp_mgr_put_ctx(ctx_data);
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
mutex_unlock(&ctx_data->ctx_mutex);
mutex_unlock(&hw_mgr->hw_mgr_mutex);
return rc;
@@ -4898,6 +4911,7 @@ static int cam_icp_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
hw_mgr->iommu_sec_hdl,
hw_cmd_args->u.pf_args.buf_info,
hw_cmd_args->u.pf_args.mem_found);
+
break;
default:
CAM_ERR(CAM_ICP, "Invalid cmd");
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
index 234643e3d105..5a93df33925f 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -128,11 +128,11 @@ struct clk_work_data {
};
/**
- * struct icp_frame_info
- * @request_id: request id
- * @io_config: the address of io config
- * @hfi_cfg_io_cmd: command struct to be sent to hfi
- */
+ * struct icp_frame_info
+ * @request_id: request id
+ * @io_config: the address of io config
+ * @hfi_cfg_io_cmd: command struct to be sent to hfi
+ */
struct icp_frame_info {
uint64_t request_id;
uint64_t io_config;
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
index 7bb9b9ed18a2..2ebe41417d1d 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -23,7 +23,7 @@
#define CAM_ICP_A5_BW_BYTES_VOTE 40000000
-#define CAM_ICP_CTX_MAX 36
+#define CAM_ICP_CTX_MAX 54
#define CPAS_IPE1_BIT 0x2000
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/ipe_hw/ipe_core.c
index 142fcdc6017d..1f71c7d4cd36 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/ipe_hw/ipe_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/ipe_hw/ipe_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -222,6 +222,12 @@ static int cam_ipe_cmd_reset(struct cam_hw_soc_info *soc_info,
bool reset_ipe_top_fail = false;
CAM_DBG(CAM_ICP, "CAM_ICP_IPE_CMD_RESET");
+ if (!core_info->clk_enable || !core_info->cpas_start) {
+ CAM_ERR(CAM_HFI, "IPE reset failed. clk_en %d cpas_start %d",
+ core_info->clk_enable, core_info->cpas_start);
+ return -EINVAL;
+ }
+
/* IPE CDM core reset*/
cam_io_w_mb((uint32_t)0xF,
soc_info->reg_map[0].mem_base + IPE_CDM_RST_CMD);
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c
index 113e1a8d5298..e510d7c91f49 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -29,16 +29,6 @@
static const char isp_dev_name[] = "isp";
-char *substate_name[8] = {
- "CAM_ISP_CTX_ACTIVATED_SOF",
- "CAM_ISP_CTX_ACTIVATED_APPLIED",
- "CAM_ISP_CTX_ACTIVATED_EPOCH",
- "CAM_ISP_CTX_ACTIVATED_BUBBLE",
- "CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED",
- "CAM_ISP_CTX_ACTIVATED_HW_ERROR",
- "CAM_ISP_CTX_ACTIVATED_HALT",
- "CAM_ISP_CTX_ACTIVATED_MAX",
-};
#define INC_STATE_MONITOR_HEAD(head) \
(atomic64_add_return(1, head) % \
CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES)
@@ -139,6 +129,8 @@ static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp)
size_t len = 0;
uint32_t *buf_addr;
uint32_t *buf_start, *buf_end;
+ size_t remain_len = 0;
+ bool need_put = false;
for (i = 0; i < req_isp->num_cfg; i++) {
rc = cam_packet_util_get_cmd_mem_addr(
@@ -148,16 +140,27 @@ static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp)
"Failed to get_cmd_mem_addr, rc=%d",
rc);
} else {
+ if (req_isp->cfg[i].offset >= len) {
+ CAM_ERR(CAM_ISP, "Invalid offset");
+ need_put = true;
+ goto put;
+ }
+ remain_len = len - req_isp->cfg[i].offset;
+
+ if (req_isp->cfg[i].len > remain_len) {
+ CAM_ERR(CAM_ISP, "Invalid offset");
+ need_put = true;
+ }
+put:
+ if (need_put) {
+ need_put = false;
+ continue;
+ }
+
buf_start = (uint32_t *)((uint8_t *) buf_addr +
req_isp->cfg[i].offset);
buf_end = (uint32_t *)((uint8_t *) buf_start +
req_isp->cfg[i].len - 1);
- if (len < (buf_end - buf_start + 1)) {
- CAM_DBG(CAM_ISP,
- "Invalid len %zu, buf_start-end=%d",
- len, (buf_end - buf_start + 1));
- continue;
- }
cam_cdm_util_dump_cmd_buf(buf_start, buf_end);
}
}
@@ -426,11 +429,12 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
}
if (!req_isp->bubble_detected) {
- CAM_INFO(CAM_ISP,
- "Sync with success: req %lld res 0x%x fd 0x%x",
+ CAM_DBG(CAM_ISP,
+ "Sync with success: req %lld res 0x%x fd 0x%x, ctx %u",
req->request_id,
req_isp->fence_map_out[j].resource_handle,
- req_isp->fence_map_out[j].sync_id);
+ req_isp->fence_map_out[j].sync_id,
+ ctx->ctx_id);
rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
CAM_SYNC_STATE_SIGNALED_SUCCESS);
@@ -438,11 +442,12 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
CAM_DBG(CAM_ISP, "Sync failed with rc = %d",
rc);
} else if (!req_isp->bubble_report) {
- CAM_INFO(CAM_ISP,
- "Sync with failure: req %lld res 0x%x fd 0x%x",
+ CAM_ERR(CAM_ISP,
+ "Sync with failure: req %lld res 0x%x fd 0x%x, ctx %u",
req->request_id,
req_isp->fence_map_out[j].resource_handle,
- req_isp->fence_map_out[j].sync_id);
+ req_isp->fence_map_out[j].sync_id,
+ ctx->ctx_id);
rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
CAM_SYNC_STATE_SIGNALED_ERROR);
@@ -463,9 +468,9 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
continue;
}
- CAM_DBG(CAM_ISP, "req %lld, reset sync id 0x%x",
+ CAM_DBG(CAM_ISP, "req %lld, reset sync id 0x%x ctx %u",
req->request_id,
- req_isp->fence_map_out[j].sync_id);
+ req_isp->fence_map_out[j].sync_id, ctx->ctx_id);
if (!rc) {
req_isp->num_acked++;
req_isp->fence_map_out[j].sync_id = -1;
@@ -475,9 +480,9 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
if (req_isp->num_acked > req_isp->num_fence_map_out) {
/* Should not happen */
CAM_ERR(CAM_ISP,
- "WARNING: req_id %lld num_acked %d > map_out %d",
+ "WARNING: req_id %lld num_acked %d > map_out %d, ctx %u",
req->request_id, req_isp->num_acked,
- req_isp->num_fence_map_out);
+ req_isp->num_fence_map_out, ctx->ctx_id);
WARN_ON(req_isp->num_acked > req_isp->num_fence_map_out);
}
@@ -491,17 +496,18 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
req_isp->bubble_detected = false;
list_del_init(&req->list);
list_add(&req->list, &ctx->pending_req_list);
+ atomic_set(&ctx_isp->process_bubble, 0);
CAM_DBG(CAM_REQ,
- "Move active request %lld to pending list(cnt = %d) [bubble recovery]",
- req->request_id, ctx_isp->active_req_cnt);
+ "Move active request %lld to pending list(cnt = %d) [bubble recovery], ctx %u",
+ req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
} else {
list_del_init(&req->list);
list_add_tail(&req->list, &ctx->free_req_list);
CAM_DBG(CAM_REQ,
- "Move active request %lld to free list(cnt = %d) [all fences done]",
- req->request_id, ctx_isp->active_req_cnt);
+ "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u",
+ req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
}
end:
@@ -571,7 +577,6 @@ static void __cam_isp_ctx_send_sof_timestamp(
static int __cam_isp_ctx_reg_upd_in_epoch_state(
struct cam_isp_context *ctx_isp, void *evt_data)
{
- CAM_INFO(CAM_ISP, "state = %s IRQ is RUP", substate_name[ctx_isp->substate_activated]);
if (ctx_isp->frame_id == 1)
CAM_DBG(CAM_ISP, "Reg update for early PCR");
else
@@ -589,7 +594,6 @@ static int __cam_isp_ctx_reg_upd_in_activated_state(
struct cam_context *ctx = ctx_isp->base;
struct cam_isp_ctx_req *req_isp;
- CAM_INFO(CAM_ISP, "state = %s IRQ is RUP", substate_name[ctx_isp->substate_activated]);
if (list_empty(&ctx->wait_req_list)) {
CAM_ERR(CAM_ISP, "Reg upd ack with no waiting request");
goto end;
@@ -602,14 +606,15 @@ static int __cam_isp_ctx_reg_upd_in_activated_state(
if (req_isp->num_fence_map_out != 0) {
list_add_tail(&req->list, &ctx->active_req_list);
ctx_isp->active_req_cnt++;
- CAM_DBG(CAM_REQ, "move request %lld to active list(cnt = %d)",
- req->request_id, ctx_isp->active_req_cnt);
+ CAM_DBG(CAM_REQ,
+ "move request %lld to active list(cnt = %d), ctx %u",
+ req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
} else {
/* no io config, so the request is completed. */
list_add_tail(&req->list, &ctx->free_req_list);
CAM_DBG(CAM_ISP,
- "move active request %lld to free list(cnt = %d)",
- req->request_id, ctx_isp->active_req_cnt);
+ "move active request %lld to free list(cnt = %d), ctx %u",
+ req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
}
/*
@@ -617,7 +622,6 @@ static int __cam_isp_ctx_reg_upd_in_activated_state(
* state so change substate here.
*/
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
end:
@@ -633,7 +637,6 @@ static int __cam_isp_ctx_notify_sof_in_activated_state(
struct cam_ctx_request *req;
uint64_t request_id = 0;
- CAM_INFO(CAM_ISP, "state = %s IRQ is EPOCH", substate_name[ctx_isp->substate_activated]);
/*
* notify reqmgr with sof signal. Note, due to scheduling delay
* we can run into situation that two active requests has already
@@ -650,8 +653,8 @@ static int __cam_isp_ctx_notify_sof_in_activated_state(
notify.trigger = CAM_TRIGGER_POINT_SOF;
ctx->ctx_crm_intf->notify_trigger(&notify);
- CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld",
- ctx_isp->frame_id);
+ CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld ctx %u",
+ ctx_isp->frame_id, ctx->ctx_id);
}
list_for_each_entry(req, &ctx->active_req_list, list) {
@@ -668,7 +671,9 @@ static int __cam_isp_ctx_notify_sof_in_activated_state(
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
} else {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not notify SOF to CRM");
+ CAM_ERR_RATE_LIMIT(CAM_ISP,
+ "Can not notify SOF to CRM for ctx %u",
+ ctx->ctx_id);
rc = -EFAULT;
}
@@ -693,14 +698,14 @@ static int __cam_isp_ctx_notify_eof_in_activated_state(
notify.trigger = CAM_TRIGGER_POINT_EOF;
ctx->ctx_crm_intf->notify_trigger(&notify);
- CAM_DBG(CAM_ISP, "Notify CRM EOF frame %lld\n",
- ctx_isp->frame_id);
+ CAM_DBG(CAM_ISP, "Notify CRM EOF frame %lld ctx %u",
+ ctx_isp->frame_id, ctx->ctx_id);
} else {
- CAM_ERR(CAM_ISP, "Can not notify EOF to CRM");
+ CAM_ERR(CAM_ISP, "Can not notify EOF to CRM for ctx %u",
+ ctx->ctx_id);
rc = -EFAULT;
}
- CAM_INFO(CAM_ISP, "state = %s IRQ is EOF", substate_name[ctx_isp->substate_activated]);
return rc;
}
@@ -708,7 +713,6 @@ static int __cam_isp_ctx_reg_upd_in_hw_error(
struct cam_isp_context *ctx_isp, void *evt_data)
{
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
return 0;
}
@@ -733,11 +737,8 @@ static int __cam_isp_ctx_sof_in_activated_state(
ctx_isp->boot_timestamp = sof_event_data->boot_time;
__cam_isp_ctx_update_state_monitor_array(ctx_isp,
CAM_ISP_STATE_CHANGE_TRIGGER_SOF, req->request_id);
- CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
- ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
- CAM_INFO(CAM_ISP, "state = %s IRQ is SOF frame_id = %lld",
- substate_name[ctx_isp->substate_activated], ctx_isp->frame_id);
-
+ CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx, ctx %u",
+ ctx_isp->frame_id, ctx_isp->sof_timestamp_val, ctx->ctx_id);
return rc;
}
@@ -775,7 +776,6 @@ static int __cam_isp_ctx_reg_upd_in_sof(struct cam_isp_context *ctx_isp,
CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE,
req->request_id);
}
- CAM_INFO(CAM_ISP, "state = %s IRQ is RUP", substate_name[ctx_isp->substate_activated]);
end:
return rc;
}
@@ -788,7 +788,6 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
struct cam_context *ctx = ctx_isp->base;
uint64_t request_id = 0;
- CAM_INFO(CAM_ISP, "state = %s IRQ is EPOCH", substate_name[ctx_isp->substate_activated]);
if (list_empty(&ctx->wait_req_list)) {
/*
* If no wait req in epoch, this is an error case.
@@ -796,7 +795,6 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
*/
CAM_ERR(CAM_ISP, "No wait request");
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
/* Send SOF event as empty frame*/
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
@@ -820,8 +818,9 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
notify.req_id = req->request_id;
notify.error = CRM_KMD_ERR_BUBBLE;
ctx->ctx_crm_intf->notify_err(&notify);
- CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld",
- ctx_isp->frame_id);
+ atomic_set(&ctx_isp->process_bubble, 1);
+ CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld, ctx %u",
+ ctx_isp->frame_id, ctx->ctx_id);
} else {
req_isp->bubble_report = 0;
}
@@ -830,8 +829,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
* Always move the request to active list. Let buf done
* function handles the rest.
*/
- CAM_DBG(CAM_REQ, "move request %lld to active list(cnt = %d)",
- req->request_id, ctx_isp->active_req_cnt);
+ CAM_DBG(CAM_REQ, "move request %lld to active list(cnt = %d), ctx %u",
+ req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
ctx_isp->active_req_cnt++;
list_del_init(&req->list);
list_add_tail(&req->list, &ctx->active_req_list);
@@ -844,7 +843,6 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
CAM_REQ_MGR_SOF_EVENT_ERROR);
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
CAM_DBG(CAM_ISP, "next substate %d",
ctx_isp->substate_activated);
end:
@@ -868,7 +866,6 @@ static int __cam_isp_ctx_buf_done_in_applied(struct cam_isp_context *ctx_isp,
struct cam_isp_hw_done_event_data *done =
(struct cam_isp_hw_done_event_data *) evt_data;
- CAM_INFO(CAM_ISP, "state = %s IRQ is BUF_DONE", substate_name[ctx_isp->substate_activated]);
rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 0);
return rc;
}
@@ -882,9 +879,6 @@ static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp,
struct cam_isp_hw_sof_event_data *sof_event_data = evt_data;
struct cam_ctx_request *req;
- CAM_INFO(CAM_ISP, "SURESH: state = %s IRQ is SOF frame_id = %lld",
- substate_name[ctx_isp->substate_activated], ctx_isp->frame_id);
-
if (!evt_data) {
CAM_ERR(CAM_ISP, "in valid sof event data");
return -EINVAL;
@@ -898,7 +892,6 @@ static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp,
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
else
CAM_DBG(CAM_ISP, "Still need to wait for the buf done");
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
req = list_last_entry(&ctx->active_req_list,
struct cam_ctx_request, list);
@@ -919,7 +912,6 @@ static int __cam_isp_ctx_buf_done_in_epoch(struct cam_isp_context *ctx_isp,
struct cam_isp_hw_done_event_data *done =
(struct cam_isp_hw_done_event_data *) evt_data;
- CAM_INFO(CAM_ISP, "state = %s IRQ is BUF_DONE", substate_name[ctx_isp->substate_activated]);
rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 0);
return rc;
}
@@ -931,7 +923,6 @@ static int __cam_isp_ctx_buf_done_in_bubble(
struct cam_isp_hw_done_event_data *done =
(struct cam_isp_hw_done_event_data *) evt_data;
- CAM_INFO(CAM_ISP, "state = %s IRQ is BUF_DONE", substate_name[ctx_isp->substate_activated]);
rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 1);
return rc;
}
@@ -944,7 +935,6 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
struct cam_context *ctx = ctx_isp->base;
uint64_t request_id = 0;
- CAM_INFO(CAM_ISP, "state = %s IRQ is BUF_DONE", substate_name[ctx_isp->substate_activated]);
/*
* This means we missed the reg upd ack. So we need to
* transition to BUBBLE state again.
@@ -960,7 +950,6 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
goto end;
}
@@ -979,8 +968,8 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
notify.error = CRM_KMD_ERR_BUBBLE;
ctx->ctx_crm_intf->notify_err(&notify);
CAM_DBG(CAM_REQ,
- "Notify CRM about Bubble req_id %llu frame %lld",
- req->request_id, ctx_isp->frame_id);
+ "Notify CRM about Bubble req_id %llu frame %lld, ctx %u",
+ req->request_id, ctx_isp->frame_id, ctx->ctx_id);
} else {
req_isp->bubble_report = 0;
}
@@ -989,7 +978,7 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
* Always move the request to active list. Let buf done
* function handles the rest.
*/
- CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)",
+ CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d) ctx %u",
req->request_id, ctx_isp->active_req_cnt);
ctx_isp->active_req_cnt++;
list_del_init(&req->list);
@@ -1009,7 +998,6 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
end:
req = list_last_entry(&ctx->active_req_list, struct cam_ctx_request,
@@ -1027,7 +1015,6 @@ static int __cam_isp_ctx_buf_done_in_bubble_applied(
struct cam_isp_hw_done_event_data *done =
(struct cam_isp_hw_done_event_data *) evt_data;
- CAM_INFO(CAM_ISP, "state = %s IRQ is BUF_DONE", substate_name[ctx_isp->substate_activated]);
rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 1);
__cam_isp_ctx_update_state_monitor_array(ctx_isp,
CAM_ISP_STATE_CHANGE_TRIGGER_DONE,
@@ -1050,6 +1037,7 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp,
struct cam_req_mgr_error_notify notify;
uint64_t error_request_id = 0;
struct cam_hw_fence_map_entry *fence_map_out = NULL;
+ struct cam_req_mgr_message req_msg;
struct cam_context *ctx = ctx_isp->base;
struct cam_isp_hw_error_event_data *error_event_data =
@@ -1084,7 +1072,9 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp,
}
req_isp = (struct cam_isp_ctx_req *) req_to_dump->req_priv;
- cam_isp_ctx_dump_req(req_isp);
+
+ if (error_event_data->enable_reg_dump)
+ cam_isp_ctx_dump_req(req_isp);
__cam_isp_ctx_update_state_monitor_array(ctx_isp,
CAM_ISP_STATE_CHANGE_TRIGGER_ERROR, req_to_dump->request_id);
@@ -1096,9 +1086,11 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp,
for (i = 0; i < req_isp->num_fence_map_out; i++) {
fence_map_out =
&req_isp->fence_map_out[i];
- CAM_ERR(CAM_ISP, "req %llu, Sync fd %x",
+ CAM_ERR(CAM_ISP,
+ "req %llu, Sync fd 0x%x ctx %u",
req->request_id,
- req_isp->fence_map_out[i].sync_id);
+ req_isp->fence_map_out[i].sync_id,
+ ctx->ctx_id);
if (req_isp->fence_map_out[i].sync_id != -1) {
rc = cam_sync_signal(
fence_map_out->sync_id,
@@ -1125,9 +1117,11 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp,
for (i = 0; i < req_isp->num_fence_map_out; i++) {
fence_map_out =
&req_isp->fence_map_out[i];
- CAM_ERR(CAM_ISP, "req %llu, Sync fd %x",
+ CAM_ERR(CAM_ISP,
+ "req %llu, Sync fd 0x%x ctx %u",
req->request_id,
- req_isp->fence_map_out[i].sync_id);
+ req_isp->fence_map_out[i].sync_id,
+ ctx->ctx_id);
if (req_isp->fence_map_out[i].sync_id != -1) {
rc = cam_sync_signal(
fence_map_out->sync_id,
@@ -1214,14 +1208,39 @@ end:
notify.error = CRM_KMD_ERR_FATAL;
}
- CAM_WARN(CAM_ISP, "Notify CRM: req %lld, frame %lld\n",
- error_request_id, ctx_isp->frame_id);
+ CAM_WARN(CAM_ISP, "Notify CRM: req %lld, frame %lld ctx %u",
+ error_request_id, ctx_isp->frame_id, ctx->ctx_id);
ctx->ctx_crm_intf->notify_err(&notify);
+
+ /*
+ * Need to send error occurred in KMD
+ * This will help UMD to take necessary action
+ * and to dump relevant info
+ */
+
+ if (notify.error == CRM_KMD_ERR_OVERFLOW) {
+ req_msg.session_hdl = ctx_isp->base->session_hdl;
+ req_msg.u.err_msg.device_hdl = ctx_isp->base->dev_hdl;
+ req_msg.u.err_msg.error_type =
+ CAM_REQ_MGR_ERROR_TYPE_RECOVERY;
+ req_msg.u.err_msg.link_hdl = ctx_isp->base->link_hdl;
+ req_msg.u.err_msg.request_id = error_request_id;
+ req_msg.u.err_msg.resource_size = 0x0;
+
+ if (cam_req_mgr_notify_message(&req_msg,
+ V4L_EVENT_CAM_REQ_MGR_ERROR,
+ V4L_EVENT_CAM_REQ_MGR_EVENT))
+ CAM_ERR(CAM_ISP,
+ "Error in notifying the error time for req id:%lld ctx %u",
+ ctx_isp->last_applied_req_id,
+ ctx->ctx_id);
+ }
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_HW_ERROR;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
} else {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not notify ERRROR to CRM");
+ CAM_ERR_RATE_LIMIT(CAM_ISP,
+ "Can not notify ERRROR to CRM for ctx %u",
+ ctx->ctx_id);
rc = -EFAULT;
}
@@ -1230,6 +1249,236 @@ end:
return rc;
}
+static int __cam_isp_ctx_fs2_sof_in_sof_state(
+ struct cam_isp_context *ctx_isp, void *evt_data)
+{
+ int rc = 0;
+ struct cam_isp_hw_sof_event_data *sof_event_data = evt_data;
+ struct cam_ctx_request *req;
+ struct cam_context *ctx = ctx_isp->base;
+ struct cam_req_mgr_trigger_notify notify;
+ uint64_t request_id = 0;
+
+
+ req = list_last_entry(&ctx->pending_req_list,
+ struct cam_ctx_request, list);
+
+ if (!evt_data) {
+ CAM_ERR(CAM_ISP, "in valid sof event data");
+ return -EINVAL;
+ }
+
+ ctx_isp->frame_id++;
+ ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+ ctx_isp->boot_timestamp = sof_event_data->boot_time;
+ __cam_isp_ctx_update_state_monitor_array(ctx_isp,
+ CAM_ISP_STATE_CHANGE_TRIGGER_SOF, req->request_id);
+ CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
+ ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
+
+ if (!(list_empty(&ctx->wait_req_list)))
+ goto end;
+
+ if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger &&
+ ctx_isp->active_req_cnt <= 2) {
+ if (ctx_isp->subscribe_event & CAM_TRIGGER_POINT_SOF) {
+ notify.link_hdl = ctx->link_hdl;
+ notify.dev_hdl = ctx->dev_hdl;
+ notify.frame_id = ctx_isp->frame_id;
+ notify.trigger = CAM_TRIGGER_POINT_SOF;
+
+ ctx->ctx_crm_intf->notify_trigger(&notify);
+ CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld",
+ ctx_isp->frame_id);
+ }
+
+ list_for_each_entry(req, &ctx->active_req_list, list) {
+ if (req->request_id > ctx_isp->reported_req_id) {
+ request_id = req->request_id;
+ ctx_isp->reported_req_id = request_id;
+ break;
+ }
+ }
+
+ __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+ CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+ } else {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not notify SOF to CRM");
+ rc = -EFAULT;
+ }
+
+end:
+ return rc;
+}
+
+static int __cam_isp_ctx_fs2_buf_done(struct cam_isp_context *ctx_isp,
+ void *evt_data)
+{
+ int rc = 0;
+ struct cam_isp_hw_done_event_data *done =
+ (struct cam_isp_hw_done_event_data *) evt_data;
+ struct cam_context *ctx = ctx_isp->base;
+ int prev_active_req_cnt = 0;
+ int curr_req_id = 0;
+ struct cam_ctx_request *req;
+
+ prev_active_req_cnt = ctx_isp->active_req_cnt;
+ req = list_first_entry(&ctx->active_req_list,
+ struct cam_ctx_request, list);
+ if (req)
+ curr_req_id = req->request_id;
+
+ rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 0);
+
+ if (prev_active_req_cnt == ctx_isp->active_req_cnt + 1) {
+ if (list_empty(&ctx->wait_req_list) &&
+ list_empty(&ctx->active_req_list)) {
+ CAM_DBG(CAM_ISP, "No request, move to SOF");
+ ctx_isp->substate_activated =
+ CAM_ISP_CTX_ACTIVATED_SOF;
+ if (ctx_isp->reported_req_id < curr_req_id) {
+ ctx_isp->reported_req_id = curr_req_id;
+ __cam_isp_ctx_send_sof_timestamp(ctx_isp,
+ curr_req_id,
+ CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+ }
+ }
+ }
+
+ return rc;
+}
+
+static int __cam_isp_ctx_fs2_buf_done_in_epoch(struct cam_isp_context *ctx_isp,
+ void *evt_data)
+{
+ int rc = 0;
+
+ rc = __cam_isp_ctx_fs2_buf_done(ctx_isp, evt_data);
+ return rc;
+}
+
+static int __cam_isp_ctx_fs2_buf_done_in_applied(
+ struct cam_isp_context *ctx_isp,
+ void *evt_data)
+{
+ int rc = 0;
+
+ rc = __cam_isp_ctx_fs2_buf_done(ctx_isp, evt_data);
+ return rc;
+}
+
+static int __cam_isp_ctx_fs2_reg_upd_in_sof(struct cam_isp_context *ctx_isp,
+ void *evt_data)
+{
+ int rc = 0;
+ struct cam_ctx_request *req = NULL;
+ struct cam_isp_ctx_req *req_isp;
+ struct cam_context *ctx = ctx_isp->base;
+
+ if (ctx->state != CAM_CTX_ACTIVATED && ctx_isp->frame_id > 1) {
+ CAM_DBG(CAM_ISP, "invalid RUP");
+ goto end;
+ }
+
+ /*
+ * This is for the first update. The initial setting will
+ * cause the reg_upd in the first frame.
+ */
+ if (!list_empty(&ctx->wait_req_list)) {
+ req = list_first_entry(&ctx->wait_req_list,
+ struct cam_ctx_request, list);
+ list_del_init(&req->list);
+ req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+ if (req_isp->num_fence_map_out == req_isp->num_acked)
+ list_add_tail(&req->list, &ctx->free_req_list);
+ else
+ CAM_ERR(CAM_ISP,
+ "receive rup in unexpected state");
+ }
+ if (req != NULL) {
+ __cam_isp_ctx_update_state_monitor_array(ctx_isp,
+ CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE,
+ req->request_id);
+ }
+end:
+ return rc;
+}
+
+static int __cam_isp_ctx_fs2_reg_upd_in_applied_state(
+ struct cam_isp_context *ctx_isp, void *evt_data)
+{
+ int rc = 0;
+ struct cam_ctx_request *req = NULL;
+ struct cam_context *ctx = ctx_isp->base;
+ struct cam_isp_ctx_req *req_isp;
+ struct cam_req_mgr_trigger_notify notify;
+ uint64_t request_id = 0;
+
+ if (list_empty(&ctx->wait_req_list)) {
+ CAM_ERR(CAM_ISP, "Reg upd ack with no waiting request");
+ goto end;
+ }
+ req = list_first_entry(&ctx->wait_req_list,
+ struct cam_ctx_request, list);
+ list_del_init(&req->list);
+
+ req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+ if (req_isp->num_fence_map_out != 0) {
+ list_add_tail(&req->list, &ctx->active_req_list);
+ ctx_isp->active_req_cnt++;
+ CAM_DBG(CAM_REQ, "move request %lld to active list(cnt = %d)",
+ req->request_id, ctx_isp->active_req_cnt);
+ } else {
+ /* no io config, so the request is completed. */
+ list_add_tail(&req->list, &ctx->free_req_list);
+ }
+
+ /*
+ * This function only called directly from applied and bubble applied
+ * state so change substate here.
+ */
+ ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH;
+ if (req_isp->num_fence_map_out != 1)
+ goto end;
+
+ if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger &&
+ ctx_isp->active_req_cnt <= 2) {
+ list_for_each_entry(req, &ctx->active_req_list, list) {
+ if (req->request_id > ctx_isp->reported_req_id) {
+ request_id = req->request_id;
+ ctx_isp->reported_req_id = request_id;
+ break;
+ }
+ }
+
+ __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+ CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+
+ if (ctx_isp->subscribe_event & CAM_TRIGGER_POINT_SOF) {
+ notify.link_hdl = ctx->link_hdl;
+ notify.dev_hdl = ctx->dev_hdl;
+ notify.frame_id = ctx_isp->frame_id;
+ notify.trigger = CAM_TRIGGER_POINT_SOF;
+
+ ctx->ctx_crm_intf->notify_trigger(&notify);
+ CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld",
+ ctx_isp->frame_id);
+ }
+ } else {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not notify SOF to CRM");
+ rc = -EFAULT;
+ }
+
+ CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
+end:
+ if (req != NULL && !rc) {
+ __cam_isp_ctx_update_state_monitor_array(ctx_isp,
+ CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH,
+ req->request_id);
+ }
+ return rc;
+}
+
static struct cam_isp_ctx_irq_ops
cam_isp_ctx_activated_state_machine_irq[CAM_ISP_CTX_ACTIVATED_MAX] = {
/* SOF */
@@ -1303,6 +1552,79 @@ static struct cam_isp_ctx_irq_ops
},
};
+static struct cam_isp_ctx_irq_ops
+ cam_isp_ctx_fs2_state_machine_irq[CAM_ISP_CTX_ACTIVATED_MAX] = {
+ /* SOF */
+ {
+ .irq_ops = {
+ __cam_isp_ctx_handle_error,
+ __cam_isp_ctx_fs2_sof_in_sof_state,
+ __cam_isp_ctx_fs2_reg_upd_in_sof,
+ __cam_isp_ctx_fs2_sof_in_sof_state,
+ __cam_isp_ctx_notify_eof_in_activated_state,
+ NULL,
+ },
+ },
+ /* APPLIED */
+ {
+ .irq_ops = {
+ __cam_isp_ctx_handle_error,
+ __cam_isp_ctx_sof_in_activated_state,
+ __cam_isp_ctx_fs2_reg_upd_in_applied_state,
+ __cam_isp_ctx_epoch_in_applied,
+ __cam_isp_ctx_notify_eof_in_activated_state,
+ __cam_isp_ctx_fs2_buf_done_in_applied,
+ },
+ },
+ /* EPOCH */
+ {
+ .irq_ops = {
+ __cam_isp_ctx_handle_error,
+ __cam_isp_ctx_sof_in_epoch,
+ __cam_isp_ctx_reg_upd_in_epoch_state,
+ __cam_isp_ctx_notify_sof_in_activated_state,
+ __cam_isp_ctx_notify_eof_in_activated_state,
+ __cam_isp_ctx_fs2_buf_done_in_epoch,
+ },
+ },
+ /* BUBBLE */
+ {
+ .irq_ops = {
+ __cam_isp_ctx_handle_error,
+ __cam_isp_ctx_sof_in_activated_state,
+ NULL,
+ __cam_isp_ctx_notify_sof_in_activated_state,
+ __cam_isp_ctx_notify_eof_in_activated_state,
+ __cam_isp_ctx_buf_done_in_bubble,
+ },
+ },
+ /* Bubble Applied */
+ {
+ .irq_ops = {
+ __cam_isp_ctx_handle_error,
+ __cam_isp_ctx_sof_in_activated_state,
+ __cam_isp_ctx_reg_upd_in_activated_state,
+ __cam_isp_ctx_epoch_in_bubble_applied,
+ NULL,
+ __cam_isp_ctx_buf_done_in_bubble_applied,
+ },
+ },
+ /* HW ERROR */
+ {
+ .irq_ops = {
+ NULL,
+ __cam_isp_ctx_sof_in_activated_state,
+ __cam_isp_ctx_reg_upd_in_hw_error,
+ NULL,
+ NULL,
+ NULL,
+ },
+ },
+ /* HALT */
+ {
+ },
+};
+
static int __cam_isp_ctx_apply_req_in_activated_state(
struct cam_context *ctx, struct cam_req_mgr_apply_request *apply,
uint32_t next_state)
@@ -1330,6 +1652,14 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
*/
ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
+ if (atomic_read(&ctx_isp->process_bubble)) {
+ CAM_DBG(CAM_ISP,
+ "Processing bubble cannot apply Request Id %llu",
+ apply->request_id);
+ rc = -EAGAIN;
+ goto end;
+ }
+
spin_lock_bh(&ctx->lock);
req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request,
list);
@@ -1347,15 +1677,16 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
goto end;
}
- CAM_DBG(CAM_REQ, "Apply request %lld in substate %d", req->request_id,
- ctx_isp->substate_activated);
+ CAM_DBG(CAM_REQ, "Apply request %lld in substate %d ctx %u",
+ req->request_id, ctx_isp->substate_activated, ctx->ctx_id);
req_isp = (struct cam_isp_ctx_req *) req->req_priv;
if (ctx_isp->active_req_cnt >= 2) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
- "Reject apply request (id %lld) due to congestion(cnt = %d)",
+ "Reject apply request (id %lld) due to congestion(cnt = %d) ctx %u",
req->request_id,
- ctx_isp->active_req_cnt);
+ ctx_isp->active_req_cnt,
+ ctx->ctx_id);
spin_lock_bh(&ctx->lock);
if (!list_empty(&ctx->active_req_list))
@@ -1391,7 +1722,6 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
} else {
spin_lock_bh(&ctx->lock);
ctx_isp->substate_activated = next_state;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
ctx_isp->last_applied_req_id = apply->request_id;
list_del_init(&req->list);
list_add_tail(&req->list, &ctx->wait_req_list);
@@ -1420,7 +1750,6 @@ static int __cam_isp_ctx_apply_req_in_sof(
rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
CAM_ISP_CTX_ACTIVATED_APPLIED);
CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated);
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
return rc;
}
@@ -1437,7 +1766,6 @@ static int __cam_isp_ctx_apply_req_in_epoch(
rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
CAM_ISP_CTX_ACTIVATED_APPLIED);
CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated);
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
return rc;
}
@@ -1454,7 +1782,6 @@ static int __cam_isp_ctx_apply_req_in_bubble(
rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED);
CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated);
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
return rc;
}
@@ -1528,11 +1855,6 @@ static int __cam_isp_ctx_flush_req_in_top_state(
struct cam_context *ctx,
struct cam_req_mgr_flush_request *flush_req)
{
- struct cam_isp_context *ctx_isp =
- (struct cam_isp_context *) ctx->ctx_priv;
- struct cam_isp_stop_args stop_isp;
- struct cam_hw_stop_args stop_args;
- struct cam_isp_start_args start_isp;
int rc = 0;
if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
@@ -1546,47 +1868,6 @@ static int __cam_isp_ctx_flush_req_in_top_state(
rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
spin_unlock_bh(&ctx->lock);
- if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
- /* if active and wait list are empty, return */
- spin_lock_bh(&ctx->lock);
- if ((list_empty(&ctx->wait_req_list)) &&
- (list_empty(&ctx->active_req_list))) {
- spin_unlock_bh(&ctx->lock);
- CAM_DBG(CAM_ISP, "active and wait list are empty");
- goto end;
- }
- spin_unlock_bh(&ctx->lock);
-
- /* Stop hw first before active list flush */
- stop_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
- stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY;
- stop_isp.stop_only = true;
- stop_args.args = (void *)&stop_isp;
- ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv,
- &stop_args);
-
- spin_lock_bh(&ctx->lock);
- CAM_DBG(CAM_ISP, "try to flush wait list");
- rc = __cam_isp_ctx_flush_req(ctx, &ctx->wait_req_list,
- flush_req);
- CAM_DBG(CAM_ISP, "try to flush active list");
- rc = __cam_isp_ctx_flush_req(ctx, &ctx->active_req_list,
- flush_req);
- ctx_isp->active_req_cnt = 0;
- spin_unlock_bh(&ctx->lock);
-
- /* Start hw */
- start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx;
- start_isp.start_only = true;
- start_isp.hw_config.priv = NULL;
-
- rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv,
- &start_isp);
- }
-
-end:
- CAM_DBG(CAM_ISP, "Flush request in top state %d",
- ctx->state);
return rc;
}
@@ -1664,6 +1945,58 @@ static struct cam_ctx_ops
},
};
+static struct cam_ctx_ops
+ cam_isp_ctx_fs2_state_machine[CAM_ISP_CTX_ACTIVATED_MAX] = {
+ /* SOF */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {
+ .apply_req = __cam_isp_ctx_apply_req_in_sof,
+ },
+ .irq_ops = NULL,
+ },
+ /* APPLIED */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {},
+ .irq_ops = NULL,
+ },
+ /* EPOCH */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {
+ .apply_req = __cam_isp_ctx_apply_req_in_epoch,
+ },
+ .irq_ops = NULL,
+ },
+ /* BUBBLE */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {
+ .apply_req = __cam_isp_ctx_apply_req_in_bubble,
+ },
+ .irq_ops = NULL,
+ },
+ /* Bubble Applied */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {},
+ .irq_ops = NULL,
+ },
+ /* HW ERROR */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {},
+ .irq_ops = NULL,
+ },
+ /* HALT */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {},
+ .irq_ops = NULL,
+ },
+};
+
static int __cam_isp_ctx_rdi_only_sof_in_top_state(
struct cam_isp_context *ctx_isp, void *evt_data)
{
@@ -1718,7 +2051,6 @@ static int __cam_isp_ctx_rdi_only_sof_in_top_state(
else
CAM_DBG(CAM_ISP, "Still need to wait for the buf done");
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
CAM_DBG(CAM_ISP, "next substate %d",
ctx_isp->substate_activated);
return rc;
@@ -1741,7 +2073,6 @@ static int __cam_isp_ctx_rdi_only_sof_in_applied_state(
ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
return 0;
@@ -1780,7 +2111,6 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied(
*/
CAM_ERR(CAM_ISP, "No wait request");
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
/* Send SOF event as empty frame*/
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
@@ -1835,7 +2165,6 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied(
/* change the state to bubble, as reg update has not come */
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
end:
return 0;
@@ -1906,7 +2235,6 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state(
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
CAM_DBG(CAM_ISP, "next substate %d",
ctx_isp->substate_activated);
@@ -1924,7 +2252,6 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state(
uint64_t request_id = 0;
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
/* notify reqmgr with sof signal*/
if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) {
if (list_empty(&ctx->wait_req_list)) {
@@ -1986,7 +2313,6 @@ error:
* to SOF sub state
*/
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
return 0;
}
@@ -2069,7 +2395,6 @@ static int __cam_isp_ctx_rdi_only_apply_req_top_state(
rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
CAM_ISP_CTX_ACTIVATED_APPLIED);
CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated);
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
return rc;
}
@@ -2125,9 +2450,8 @@ static struct cam_ctx_ops
},
};
-/* top level state machine */
-static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
- struct cam_release_dev_cmd *cmd)
+static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx,
+ void *cmd)
{
int rc = 0;
struct cam_hw_release_args rel_arg;
@@ -2135,28 +2459,16 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
(struct cam_isp_context *) ctx->ctx_priv;
struct cam_req_mgr_flush_request flush_req;
- if (ctx->link_hdl != -1) {
- CAM_ERR(CAM_ISP, "ctx expects release dev after unlink");
- rc = -EAGAIN;
- return rc;
- }
-
- if (cmd && ctx_isp->hw_ctx && ctx_isp->split_acquire) {
- CAM_ERR(CAM_ISP, "ctx expects release HW before release dev");
- return rc;
- }
-
if (ctx_isp->hw_ctx) {
rel_arg.ctxt_to_hw_map = ctx_isp->hw_ctx;
ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv,
&rel_arg);
ctx_isp->hw_ctx = NULL;
+ } else {
+ CAM_ERR(CAM_ISP, "No hw resources acquired for this ctx");
}
- ctx->session_hdl = -1;
- ctx->dev_hdl = -1;
- ctx->link_hdl = -1;
- ctx->ctx_crm_intf = NULL;
+ ctx->last_flush_req = 0;
ctx_isp->frame_id = 0;
ctx_isp->active_req_cnt = 0;
ctx_isp->reported_req_id = 0;
@@ -2168,7 +2480,7 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
* But we still add some sanity check code here to help the debug
*/
if (!list_empty(&ctx->active_req_list))
- CAM_ERR(CAM_ISP, "Active list is not empty");
+ CAM_WARN(CAM_ISP, "Active list is not empty");
/* Flush all the pending request list */
flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL;
@@ -2179,7 +2491,7 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
spin_lock_bh(&ctx->lock);
rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, &flush_req);
spin_unlock_bh(&ctx->lock);
- ctx->state = CAM_CTX_AVAILABLE;
+ ctx->state = CAM_CTX_ACQUIRED;
trace_cam_context_state("ISP", ctx);
CAM_DBG(CAM_ISP, "Release device success[%u] next state %d",
@@ -2187,8 +2499,9 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
return rc;
}
-static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx,
- void *cmd)
+/* top level state machine */
+static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
+ struct cam_release_dev_cmd *cmd)
{
int rc = 0;
struct cam_hw_release_args rel_arg;
@@ -2196,15 +2509,23 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx,
(struct cam_isp_context *) ctx->ctx_priv;
struct cam_req_mgr_flush_request flush_req;
+ if (cmd && ctx_isp->hw_ctx) {
+ CAM_ERR(CAM_ISP, "releasing hw");
+ __cam_isp_ctx_release_hw_in_top_state(ctx, NULL);
+ }
+
if (ctx_isp->hw_ctx) {
rel_arg.ctxt_to_hw_map = ctx_isp->hw_ctx;
ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv,
&rel_arg);
ctx_isp->hw_ctx = NULL;
- } else {
- CAM_ERR(CAM_ISP, "No hw resources acquired for this ctx");
}
+ ctx->session_hdl = -1;
+ ctx->dev_hdl = -1;
+ ctx->link_hdl = -1;
+ ctx->ctx_crm_intf = NULL;
+ ctx->last_flush_req = 0;
ctx_isp->frame_id = 0;
ctx_isp->active_req_cnt = 0;
ctx_isp->reported_req_id = 0;
@@ -2216,7 +2537,7 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx,
* But we still add some sanity check code here to help the debug
*/
if (!list_empty(&ctx->active_req_list))
- CAM_WARN(CAM_ISP, "Active list is not empty");
+ CAM_ERR(CAM_ISP, "Active list is not empty");
/* Flush all the pending request list */
flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL;
@@ -2227,7 +2548,7 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx,
spin_lock_bh(&ctx->lock);
rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, &flush_req);
spin_unlock_bh(&ctx->lock);
- ctx->state = CAM_CTX_ACQUIRED;
+ ctx->state = CAM_CTX_AVAILABLE;
trace_cam_context_state("ISP", ctx);
CAM_DBG(CAM_ISP, "Release device success[%u] next state %d",
@@ -2244,6 +2565,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
uintptr_t packet_addr;
struct cam_packet *packet;
size_t len = 0;
+ size_t remain_len = 0;
struct cam_hw_prepare_update_args cfg;
struct cam_req_mgr_add_request add_req;
struct cam_isp_context *ctx_isp =
@@ -2278,6 +2600,14 @@ static int __cam_isp_ctx_config_dev_in_top_state(
goto free_req;
}
+ remain_len = len;
+ if ((len < sizeof(struct cam_packet)) ||
+ ((size_t)cmd->offset >= len - sizeof(struct cam_packet))) {
+ CAM_ERR(CAM_ISP, "invalid buff length: %zu or offset", len);
+ return -EINVAL;
+ }
+
+ remain_len -= (size_t)cmd->offset;
packet = (struct cam_packet *)(packet_addr + (uint32_t)cmd->offset);
CAM_DBG(CAM_ISP, "pack_handle %llx", cmd->packet_handle);
CAM_DBG(CAM_ISP, "packet address is 0x%zx", packet_addr);
@@ -2288,7 +2618,8 @@ static int __cam_isp_ctx_config_dev_in_top_state(
CAM_DBG(CAM_ISP, "Packet size 0x%x", packet->header.size);
CAM_DBG(CAM_ISP, "packet op %d", packet->header.op_code);
- if (packet->header.request_id <= ctx->last_flush_req) {
+ if ((((packet->header.op_code + 1) & 0xF) == CAM_ISP_PACKET_UPDATE_DEV)
+ && (packet->header.request_id <= ctx->last_flush_req)) {
CAM_INFO(CAM_ISP,
"request %lld has been flushed, reject packet",
packet->header.request_id);
@@ -2296,12 +2627,10 @@ static int __cam_isp_ctx_config_dev_in_top_state(
goto free_req;
}
- if (packet->header.request_id > ctx->last_flush_req)
- ctx->last_flush_req = 0;
-
/* preprocess the configuration */
memset(&cfg, 0, sizeof(cfg));
cfg.packet = packet;
+ cfg.remain_len = remain_len;
cfg.ctxt_to_hw_map = ctx_isp->hw_ctx;
cfg.max_hw_update_entries = CAM_ISP_CTX_CFG_MAX;
cfg.hw_update_entries = req_isp->cfg;
@@ -2388,8 +2717,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
put_ref:
for (--i; i >= 0; i--) {
- rc = cam_sync_put_obj_ref(req_isp->fence_map_out[i].sync_id);
- if (rc)
+ if (cam_sync_put_obj_ref(req_isp->fence_map_out[i].sync_id))
CAM_ERR(CAM_CTXT, "Failed to put ref of fence %d",
req_isp->fence_map_out[i].sync_id);
}
@@ -2476,7 +2804,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
/* Query the context has rdi only resource */
hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL;
- isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT;
+ isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_CTX_TYPE;
hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args;
rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
&hw_cmd_args);
@@ -2485,7 +2813,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
goto free_hw;
}
- if (isp_hw_cmd_args.u.is_rdi_only_context) {
+ if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_RDI) {
/*
* this context has rdi only resource assign rdi only
* state machine
@@ -2496,6 +2824,13 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
cam_isp_ctx_rdi_only_activated_state_machine_irq;
ctx_isp->substate_machine =
cam_isp_ctx_rdi_only_activated_state_machine;
+ ctx_isp->rdi_only_context = true;
+ } else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_FS2) {
+ CAM_DBG(CAM_ISP, "FS2 Session has PIX ,RD and RDI");
+ ctx_isp->substate_machine_irq =
+ cam_isp_ctx_fs2_state_machine_irq;
+ ctx_isp->substate_machine =
+ cam_isp_ctx_fs2_state_machine;
} else {
CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
ctx_isp->substate_machine_irq =
@@ -2504,7 +2839,6 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
cam_isp_ctx_activated_state_machine;
}
- ctx_isp->rdi_only_context = isp_hw_cmd_args.u.is_rdi_only_context;
ctx_isp->hw_ctx = param.ctxt_to_hw_map;
ctx_isp->hw_acquired = true;
ctx_isp->split_acquire = false;
@@ -2622,7 +2956,7 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
/* Query the context has rdi only resource */
hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL;
- isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT;
+ isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_CTX_TYPE;
hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args;
rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
&hw_cmd_args);
@@ -2631,7 +2965,7 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
goto free_hw;
}
- if (isp_hw_cmd_args.u.is_rdi_only_context) {
+ if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_RDI) {
/*
* this context has rdi only resource assign rdi only
* state machine
@@ -2642,6 +2976,13 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
cam_isp_ctx_rdi_only_activated_state_machine_irq;
ctx_isp->substate_machine =
cam_isp_ctx_rdi_only_activated_state_machine;
+ ctx_isp->rdi_only_context = true;
+ } else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_FS2) {
+ CAM_DBG(CAM_ISP, "FS2 Session has PIX ,RD and RDI");
+ ctx_isp->substate_machine_irq =
+ cam_isp_ctx_fs2_state_machine_irq;
+ ctx_isp->substate_machine =
+ cam_isp_ctx_fs2_state_machine;
} else {
CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
ctx_isp->substate_machine_irq =
@@ -2650,16 +2991,14 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
cam_isp_ctx_activated_state_machine;
}
- ctx_isp->rdi_only_context = isp_hw_cmd_args.u.is_rdi_only_context;
ctx_isp->hw_ctx = param.ctxt_to_hw_map;
ctx_isp->hw_acquired = true;
ctx->ctxt_to_hw_map = param.ctxt_to_hw_map;
trace_cam_context_state("ISP", ctx);
CAM_DBG(CAM_ISP,
- "Acquire success on session_hdl 0x%xs RDI only %d ctx %u",
- ctx->session_hdl,
- (isp_hw_cmd_args.u.is_rdi_only_context ? 1 : 0), ctx->ctx_id);
+ "Acquire success on session_hdl 0x%xs ctx_type %d ctx_id %u",
+ ctx->session_hdl, isp_hw_cmd_args.u.ctx_type, ctx->ctx_id);
kfree(acquire_hw_info);
return rc;
@@ -2814,7 +3153,6 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
CAM_ISP_CTX_ACTIVATED_APPLIED :
(req_isp->num_fence_map_out) ? CAM_ISP_CTX_ACTIVATED_EPOCH :
CAM_ISP_CTX_ACTIVATED_SOF;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
/*
* Only place to change state before calling the hw due to
@@ -2876,7 +3214,6 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock(
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_HALT;
spin_unlock_bh(&ctx->lock);
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
/* stop hw first */
if (ctx_isp->hw_ctx) {
@@ -2947,6 +3284,12 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock(
CAM_DBG(CAM_ISP, "Stop device success next state %d on ctx %u",
ctx->state, ctx->ctx_id);
+
+ if (!stop_cmd) {
+ rc = __cam_isp_ctx_unlink_in_ready(ctx, NULL);
+ if (rc)
+ CAM_ERR(CAM_ISP, "Unlink failed rc=%d", rc);
+ }
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.h b/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.h
index 5ebd82ead470..4954f2034144 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -144,6 +144,8 @@ struct cam_isp_context_state_monitor {
* @base: Common context object pointer
* @frame_id: Frame id tracking for the isp context
* @substate_actiavted: Current substate for the activated state.
+ * @process_bubble: Atomic variable to check if ctx is still
+ * processing bubble.
* @substate_machine: ISP substate machine for external interface
* @substate_machine_irq: ISP substate machine for irq handling
* @req_base: Common request object storage
@@ -170,6 +172,7 @@ struct cam_isp_context {
int64_t frame_id;
uint32_t substate_activated;
+ atomic_t process_bubble;
struct cam_ctx_ops *substate_machine;
struct cam_isp_ctx_irq_ops *substate_machine_irq;
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index a6c96bd8929c..9fb67570b51a 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -43,7 +43,7 @@
(CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON + 1)
#define CAM_ISP_GENERIC_BLOB_TYPE_MAX \
- (CAM_ISP_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG + 1)
+ (CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG + 1)
static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = {
CAM_ISP_HW_CMD_GET_HFR_UPDATE,
@@ -51,6 +51,7 @@ static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = {
CAM_ISP_HW_CMD_BW_UPDATE,
CAM_ISP_HW_CMD_UBWC_UPDATE,
CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE,
+ CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG,
};
static struct cam_ife_hw_mgr g_ife_hw_mgr;
@@ -316,6 +317,11 @@ static void cam_ife_hw_mgr_deinit_hw(
cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
}
+ /* Deint IFE RD */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+ cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
+ }
+
/* Deinit IFE OUT */
for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
cam_ife_hw_mgr_deinit_hw_res(&ctx->res_list_ife_out[i]);
@@ -366,6 +372,18 @@ static int cam_ife_hw_mgr_init_hw(
}
}
+ /* INIT IFE BUS RD */
+ CAM_DBG(CAM_ISP, "INIT IFE BUS RD in ctx id:%d",
+ ctx->ctx_index);
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+ rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Can not IFE BUS RD (%d)",
+ hw_mgr_res->res_id);
+ return rc;
+ }
+ }
+
/* INIT IFE OUT */
CAM_DBG(CAM_ISP, "INIT IFE OUT RESOURCES in ctx id:%d",
ctx->ctx_index);
@@ -500,6 +518,13 @@ static int cam_ife_hw_mgr_release_hw_for_ctx(
for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
cam_ife_hw_mgr_free_hw_res(&ife_ctx->res_list_ife_out[i]);
+ /* ife bus rd resource */
+ list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp,
+ &ife_ctx->res_list_ife_in_rd, list) {
+ cam_ife_hw_mgr_free_hw_res(hw_mgr_res);
+ cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &hw_mgr_res);
+ }
+
/* ife source resource */
list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp,
&ife_ctx->res_list_ife_src, list) {
@@ -645,6 +670,91 @@ static int cam_ife_mgr_process_base_info(
return 0;
}
+static int cam_ife_hw_mgr_acquire_res_bus_rd(
+ struct cam_ife_hw_mgr_ctx *ife_ctx,
+ struct cam_isp_in_port_info *in_port)
+{
+ int rc = -EINVAL;
+ struct cam_vfe_acquire_args vfe_acquire;
+ struct cam_ife_hw_mgr_res *ife_in_rd_res;
+ struct cam_hw_intf *hw_intf;
+ struct cam_ife_hw_mgr_res *ife_src_res;
+ int i;
+
+ CAM_DBG(CAM_ISP, "Enter");
+
+ list_for_each_entry(ife_src_res, &ife_ctx->res_list_ife_src, list) {
+ if (ife_src_res->res_id != CAM_ISP_HW_VFE_IN_RD)
+ continue;
+
+ rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list,
+ &ife_in_rd_res);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "No more free hw mgr resource");
+ goto err;
+ }
+ cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_in_rd,
+ &ife_in_rd_res);
+
+ vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_BUS_RD;
+ vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
+ vfe_acquire.vfe_out.cdm_ops = ife_ctx->cdm_ops;
+ vfe_acquire.vfe_out.ctx = ife_ctx;
+ vfe_acquire.vfe_out.unique_id = ife_ctx->ctx_index;
+ vfe_acquire.vfe_out.is_dual = ife_src_res->is_dual_vfe;
+ for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+ if (!ife_src_res->hw_res[i])
+ continue;
+
+ hw_intf = ife_src_res->hw_res[i]->hw_intf;
+ if (i == CAM_ISP_HW_SPLIT_LEFT) {
+ vfe_acquire.vfe_out.split_id =
+ CAM_ISP_HW_SPLIT_LEFT;
+ if (ife_src_res->is_dual_vfe) {
+ /*TBD */
+ vfe_acquire.vfe_out.is_master = 1;
+ vfe_acquire.vfe_out.dual_slave_core =
+ (hw_intf->hw_idx == 0) ? 1 : 0;
+ } else {
+ vfe_acquire.vfe_out.is_master = 0;
+ vfe_acquire.vfe_out.dual_slave_core =
+ 0;
+ }
+ } else {
+ vfe_acquire.vfe_out.split_id =
+ CAM_ISP_HW_SPLIT_RIGHT;
+ vfe_acquire.vfe_out.is_master = 0;
+ vfe_acquire.vfe_out.dual_slave_core =
+ (hw_intf->hw_idx == 0) ? 1 : 0;
+ }
+ rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+ &vfe_acquire,
+ sizeof(struct cam_vfe_acquire_args));
+ if (rc) {
+ CAM_ERR(CAM_ISP,
+ "Can not acquire out resource 0x%x",
+ vfe_acquire.rsrc_type);
+ goto err;
+ }
+
+ ife_in_rd_res->hw_res[i] =
+ vfe_acquire.vfe_out.rsrc_node;
+ CAM_DBG(CAM_ISP, "resource type :0x%x res id:0x%x",
+ ife_in_rd_res->hw_res[i]->res_type,
+ ife_in_rd_res->hw_res[i]->res_id);
+
+ }
+ ife_in_rd_res->is_dual_vfe = in_port->usage_type;
+ ife_in_rd_res->res_type = (enum cam_ife_hw_mgr_res_type)
+ CAM_ISP_RESOURCE_VFE_BUS_RD;
+ }
+
+ return 0;
+err:
+ CAM_DBG(CAM_ISP, "Exit rc(0x%x)", rc);
+ return rc;
+}
+
static int cam_ife_hw_mgr_acquire_res_ife_out_rdi(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_ife_hw_mgr_res *ife_src_res,
@@ -724,6 +834,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_rdi(
ife_out_res->res_type = (enum cam_ife_hw_mgr_res_type)
CAM_ISP_RESOURCE_VFE_OUT;
ife_src_res->child[ife_src_res->num_children++] = ife_out_res;
+ CAM_DBG(CAM_ISP, "IFE SRC num_children = %d",
+ ife_src_res->num_children);
return 0;
err:
@@ -817,6 +929,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_pixel(
ife_out_res->res_id = out_port->res_type;
ife_out_res->parent = ife_src_res;
ife_src_res->child[ife_src_res->num_children++] = ife_out_res;
+ CAM_DBG(CAM_ISP, "IFE SRC num_children = %d",
+ ife_src_res->num_children);
}
return 0;
@@ -839,6 +953,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_out(
switch (ife_src_res->res_id) {
case CAM_ISP_HW_VFE_IN_CAMIF:
case CAM_ISP_HW_VFE_IN_CAMIF_LITE:
+ case CAM_ISP_HW_VFE_IN_RD:
rc = cam_ife_hw_mgr_acquire_res_ife_out_pixel(ife_ctx,
ife_src_res, in_port);
break;
@@ -864,6 +979,132 @@ err:
return rc;
}
+static int cam_ife_hw_mgr_acquire_res_ife_rd_src(
+ struct cam_ife_hw_mgr_ctx *ife_ctx,
+ struct cam_isp_in_port_info *in_port)
+{
+ int rc = -1;
+ struct cam_ife_hw_mgr_res *csid_res;
+ struct cam_ife_hw_mgr_res *ife_src_res;
+ struct cam_vfe_acquire_args vfe_acquire;
+ struct cam_hw_intf *hw_intf;
+ struct cam_ife_hw_mgr *ife_hw_mgr;
+ int vfe_idx = -1, i = 0;
+
+ ife_hw_mgr = ife_ctx->hw_mgr;
+
+ CAM_DBG(CAM_ISP, "Enter");
+ list_for_each_entry(csid_res, &ife_ctx->res_list_ife_csid, list) {
+ if (csid_res->res_id != CAM_IFE_PIX_PATH_RES_RDI_0) {
+ CAM_DBG(CAM_ISP, "not RDI0: %d", csid_res->res_id);
+ continue;
+ }
+
+ rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list,
+ &ife_src_res);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "No more free hw mgr resource");
+ goto err;
+ }
+ cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_src,
+ &ife_src_res);
+
+ CAM_DBG(CAM_ISP, "csid_res_id %d", csid_res->res_id);
+ vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_IN;
+ vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
+ vfe_acquire.vfe_in.cdm_ops = ife_ctx->cdm_ops;
+ vfe_acquire.vfe_in.in_port = in_port;
+ vfe_acquire.vfe_in.res_id = CAM_ISP_HW_VFE_IN_RD;
+ vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE;
+
+ ife_src_res->res_type =
+ (enum cam_ife_hw_mgr_res_type)vfe_acquire.rsrc_type;
+ ife_src_res->res_id = vfe_acquire.vfe_in.res_id;
+ ife_src_res->is_dual_vfe = csid_res->is_dual_vfe;
+
+ hw_intf =
+ ife_hw_mgr->ife_devices[csid_res->hw_res[
+ CAM_ISP_HW_SPLIT_LEFT]->hw_intf->hw_idx];
+
+ vfe_idx = csid_res->hw_res[
+ CAM_ISP_HW_SPLIT_LEFT]->hw_intf->hw_idx;
+
+ /*
+ * fill in more acquire information as needed
+ */
+ if (ife_src_res->is_dual_vfe)
+ vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_MASTER;
+
+ rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+ &vfe_acquire,
+ sizeof(struct cam_vfe_acquire_args));
+ if (rc) {
+ CAM_ERR(CAM_ISP,
+ "Can not acquire IFE HW res %d",
+ csid_res->res_id);
+ goto err;
+ }
+ ife_src_res->hw_res[CAM_ISP_HW_SPLIT_LEFT] =
+ vfe_acquire.vfe_in.rsrc_node;
+ CAM_DBG(CAM_ISP,
+ "acquire success IFE:%d res type :0x%x res id:0x%x",
+ hw_intf->hw_idx,
+ ife_src_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]->res_type,
+ ife_src_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]->res_id);
+
+ if (!ife_src_res->is_dual_vfe)
+ goto acq;
+
+ for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+ if (i == CAM_ISP_HW_SPLIT_LEFT) {
+ CAM_DBG(CAM_ISP, "vfe_idx %d is acquired",
+ vfe_idx);
+ continue;
+ }
+
+ hw_intf = ife_hw_mgr->ife_devices[i];
+
+ /* fill in more acquire information as needed */
+ if (i == CAM_ISP_HW_SPLIT_RIGHT)
+ vfe_acquire.vfe_in.sync_mode =
+ CAM_ISP_HW_SYNC_SLAVE;
+
+ rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+ &vfe_acquire,
+ sizeof(struct cam_vfe_acquire_args));
+ if (rc) {
+ CAM_ERR(CAM_ISP,
+ "Can not acquire IFE HW res %d",
+ csid_res->res_id);
+ goto err;
+ }
+ ife_src_res->hw_res[i] = vfe_acquire.vfe_in.rsrc_node;
+ CAM_DBG(CAM_ISP,
+ "acquire success IFE:%d res type :0x%x res id:0x%x",
+ hw_intf->hw_idx,
+ ife_src_res->hw_res[i]->res_type,
+ ife_src_res->hw_res[i]->res_id);
+ }
+acq:
+ /*
+ * It should be one to one mapping between
+ * csid resource and ife source resource
+ */
+ csid_res->child[0] = ife_src_res;
+ ife_src_res->parent = csid_res;
+ csid_res->child[csid_res->num_children++] = ife_src_res;
+ CAM_DBG(CAM_ISP,
+ "csid_res=%d CSID num_children=%d ife_src_res=%d",
+ csid_res->res_id, csid_res->num_children,
+ ife_src_res->res_id);
+ }
+
+err:
+ /* release resource at the entry function */
+ CAM_DBG(CAM_ISP, "Exit rc(0x%x)", rc);
+ return rc;
+}
+
static int cam_ife_hw_mgr_acquire_res_ife_src(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_info *in_port)
@@ -976,7 +1217,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_src(
csid_res->child[0] = ife_src_res;
ife_src_res->parent = csid_res;
csid_res->child[csid_res->num_children++] = ife_src_res;
- CAM_DBG(CAM_ISP, "csid_res=%d num_children=%d ife_src_res=%d",
+ CAM_DBG(CAM_ISP,
+ "csid_res=%d CSID num_children=%d ife_src_res=%d",
csid_res->res_id, csid_res->num_children,
ife_src_res->res_id);
}
@@ -991,7 +1233,7 @@ static int cam_ife_mgr_acquire_cid_res(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_info *in_port,
struct cam_ife_hw_mgr_res **cid_res,
- enum cam_ife_pix_path_res_id csid_path)
+ enum cam_ife_pix_path_res_id path_res_id)
{
int rc = -1;
int i, j;
@@ -1015,8 +1257,8 @@ static int cam_ife_mgr_acquire_cid_res(
csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
csid_acquire.in_port = in_port;
- csid_acquire.res_id = csid_path;
- CAM_DBG(CAM_ISP, "path %d", csid_path);
+ csid_acquire.res_id = path_res_id;
+ CAM_DBG(CAM_ISP, "path_res_id %d", path_res_id);
if (in_port->num_out_res)
out_port = &(in_port->data[0]);
@@ -1049,12 +1291,12 @@ static int cam_ife_mgr_acquire_cid_res(
csid_acquire.node_res;
CAM_DBG(CAM_ISP,
- "acquired csid(%s)=%d CID rsrc successfully",
+ "acquired from old csid(%s)=%d CID rsrc successfully",
(i == 0) ? "left" : "right",
hw_intf->hw_idx);
if (in_port->usage_type && acquired_cnt == 1 &&
- csid_path == CAM_IFE_PIX_PATH_RES_IPP)
+ path_res_id == CAM_IFE_PIX_PATH_RES_IPP)
/*
* Continue to acquire Right for IPP.
* Dual IFE for RDI and PPP is not currently
@@ -1074,28 +1316,53 @@ static int cam_ife_mgr_acquire_cid_res(
}
/* Acquire Left if not already acquired */
- for (i = CAM_IFE_CSID_HW_NUM_MAX - 1; i >= 0; i--) {
- if (!ife_hw_mgr->csid_devices[i])
- continue;
+ if (ife_ctx->is_fe_enable) {
+ for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) {
+ if (!ife_hw_mgr->csid_devices[i])
+ continue;
- hw_intf = ife_hw_mgr->csid_devices[i];
- rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &csid_acquire,
- sizeof(csid_acquire));
- if (rc)
- continue;
- else {
- cid_res_temp->hw_res[acquired_cnt++] =
- csid_acquire.node_res;
- break;
+ hw_intf = ife_hw_mgr->csid_devices[i];
+ rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+ &csid_acquire, sizeof(csid_acquire));
+ if (rc)
+ continue;
+ else {
+ cid_res_temp->hw_res[acquired_cnt++] =
+ csid_acquire.node_res;
+ break;
+ }
}
- }
+ if (i == CAM_IFE_CSID_HW_NUM_MAX || !csid_acquire.node_res) {
+ CAM_ERR(CAM_ISP,
+ "Can not acquire ife cid resource for path %d",
+ path_res_id);
+ goto put_res;
+ }
+ } else {
+ for (i = CAM_IFE_CSID_HW_NUM_MAX - 1; i >= 0; i--) {
+ if (!ife_hw_mgr->csid_devices[i])
+ continue;
- if (i == -1 || !csid_acquire.node_res) {
- CAM_ERR(CAM_ISP, "Can not acquire ife cid resource for path %d",
- csid_path);
- goto put_res;
+ hw_intf = ife_hw_mgr->csid_devices[i];
+ rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+ &csid_acquire, sizeof(csid_acquire));
+ if (rc)
+ continue;
+ else {
+ cid_res_temp->hw_res[acquired_cnt++] =
+ csid_acquire.node_res;
+ break;
+ }
+ }
+ if (i == -1 || !csid_acquire.node_res) {
+ CAM_ERR(CAM_ISP,
+ "Can not acquire ife cid resource for path %d",
+ path_res_id);
+ goto put_res;
+ }
}
+
acquire_successful:
CAM_DBG(CAM_ISP, "CID left acquired success is_dual %d",
in_port->usage_type);
@@ -1114,7 +1381,7 @@ acquire_successful:
* Acquire Right if not already acquired.
* Dual IFE for RDI and PPP is not currently supported.
*/
- if (cid_res_temp->is_dual_vfe && csid_path
+ if (cid_res_temp->is_dual_vfe && path_res_id
== CAM_IFE_PIX_PATH_RES_IPP && acquired_cnt == 1) {
csid_acquire.node_res = NULL;
csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
@@ -1147,6 +1414,8 @@ acquire_successful:
cid_res_temp->parent = &ife_ctx->res_list_ife_in;
ife_ctx->res_list_ife_in.child[
ife_ctx->res_list_ife_in.num_children++] = cid_res_temp;
+ CAM_DBG(CAM_ISP, "IFE IN num_children = %d",
+ ife_ctx->res_list_ife_in.num_children);
return 0;
put_res:
@@ -1205,6 +1474,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl(
csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE;
}
+ CAM_DBG(CAM_ISP, "CSID Acq: E");
/* IPP resource needs to be from same HW as CID resource */
for (i = 0; i <= csid_res->is_dual_vfe; i++) {
CAM_DBG(CAM_ISP, "i %d is_dual %d", i, csid_res->is_dual_vfe);
@@ -1255,8 +1525,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl(
csid_res->parent = cid_res;
cid_res->child[cid_res->num_children++] = csid_res;
- CAM_DBG(CAM_ISP, "acquire res %d", csid_acquire.res_id);
-
+ CAM_DBG(CAM_ISP, "acquire res %d CID children = %d",
+ csid_acquire.res_id, cid_res->num_children);
return 0;
put_res:
cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &csid_res);
@@ -1269,6 +1539,7 @@ static enum cam_ife_pix_path_res_id
uint32_t out_port_type)
{
enum cam_ife_pix_path_res_id path_id;
+ CAM_DBG(CAM_ISP, "out_port_type %x", out_port_type);
switch (out_port_type) {
case CAM_ISP_IFE_OUT_RES_RDI_0:
@@ -1289,7 +1560,7 @@ static enum cam_ife_pix_path_res_id
break;
}
- CAM_DBG(CAM_ISP, "out_port %d path_id %d", out_port_type, path_id);
+ CAM_DBG(CAM_ISP, "out_port %x path_id %d", out_port_type, path_id);
return path_id;
}
@@ -1307,20 +1578,20 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi(
struct cam_hw_intf *hw_intf;
struct cam_isp_out_port_info *out_port;
struct cam_csid_hw_reserve_resource_args csid_acquire;
- enum cam_ife_pix_path_res_id path_type;
+ enum cam_ife_pix_path_res_id path_res_id;
ife_hw_mgr = ife_ctx->hw_mgr;
for (i = 0; i < in_port->num_out_res; i++) {
out_port = &in_port->data[i];
- path_type = cam_ife_hw_mgr_get_ife_csid_rdi_res_type(
+ path_res_id = cam_ife_hw_mgr_get_ife_csid_rdi_res_type(
out_port->res_type);
- if (path_type == CAM_IFE_PIX_PATH_RES_MAX)
+ if (path_res_id == CAM_IFE_PIX_PATH_RES_MAX)
continue;
/* get cid resource */
rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res,
- path_type);
+ path_res_id);
if (rc) {
CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed");
goto end;
@@ -1335,8 +1606,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi(
}
memset(&csid_acquire, 0, sizeof(csid_acquire));
- csid_acquire.res_id = path_type;
-
+ csid_acquire.res_id = path_res_id;
csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH;
csid_acquire.cid = cid_res->hw_res[0]->res_id;
csid_acquire.in_port = in_port;
@@ -1368,11 +1638,11 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi(
csid_res->is_dual_vfe = 0;
csid_res->hw_res[0] = csid_acquire.node_res;
csid_res->hw_res[1] = NULL;
- CAM_DBG(CAM_ISP, "acquire res %d",
- csid_acquire.res_id);
csid_res->parent = cid_res;
cid_res->child[cid_res->num_children++] =
csid_res;
+ CAM_DBG(CAM_ISP, "acquire res %d CID children = %d",
+ csid_acquire.res_id, cid_res->num_children);
cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res);
}
@@ -1395,7 +1665,8 @@ static int cam_ife_hw_mgr_acquire_res_root(
ife_ctx->res_list_ife_in.res_type = CAM_IFE_HW_MGR_RES_ROOT;
ife_ctx->res_list_ife_in.res_id = in_port->res_type;
ife_ctx->res_list_ife_in.is_dual_vfe = in_port->usage_type;
- } else if (ife_ctx->res_list_ife_in.res_id != in_port->res_type) {
+ } else if ((ife_ctx->res_list_ife_in.res_id !=
+ in_port->res_type) && (!ife_ctx->is_fe_enable)) {
CAM_ERR(CAM_ISP, "No Free resource for this context");
goto err;
} else {
@@ -1407,35 +1678,85 @@ err:
return rc;
}
-static int cam_ife_hw_mgr_preprocess_out_port(
+static int cam_ife_mgr_check_and_update_fe(
+ struct cam_ife_hw_mgr_ctx *ife_ctx,
+ struct cam_isp_acquire_hw_info *acquire_hw_info)
+{
+ int i;
+ struct cam_isp_in_port_info *in_port = NULL;
+ uint32_t in_port_length = 0;
+ uint32_t total_in_port_length = 0;
+
+ in_port = (struct cam_isp_in_port_info *)
+ ((uint8_t *)&acquire_hw_info->data +
+ acquire_hw_info->input_info_offset);
+ for (i = 0; i < acquire_hw_info->num_inputs; i++) {
+ in_port_length = sizeof(struct cam_isp_in_port_info) +
+ (in_port->num_out_res - 1) *
+ sizeof(struct cam_isp_out_port_info);
+ total_in_port_length += in_port_length;
+
+ if (total_in_port_length > acquire_hw_info->input_info_size) {
+ CAM_ERR(CAM_ISP, "buffer size is not enough");
+ return -EINVAL;
+ }
+ CAM_DBG(CAM_ISP, "in_port%d res_type %d", i,
+ in_port->res_type);
+ if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) {
+ ife_ctx->is_fe_enable = true;
+ break;
+ }
+
+ in_port = (struct cam_isp_in_port_info *)((uint8_t *)in_port +
+ in_port_length);
+ }
+ CAM_DBG(CAM_ISP, "is_fe_enable %d", ife_ctx->is_fe_enable);
+
+ return 0;
+}
+
+static int cam_ife_hw_mgr_preprocess_port(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_info *in_port,
int *ipp_count,
int *rdi_count,
- int *ppp_count)
+ int *ppp_count,
+ int *ife_rd_count)
{
int ipp_num = 0;
int rdi_num = 0;
int ppp_num = 0;
+ int ife_rd_num = 0;
uint32_t i;
struct cam_isp_out_port_info *out_port;
struct cam_ife_hw_mgr *ife_hw_mgr;
ife_hw_mgr = ife_ctx->hw_mgr;
- for (i = 0; i < in_port->num_out_res; i++) {
- out_port = &in_port->data[i];
- if (cam_ife_hw_mgr_is_rdi_res(out_port->res_type))
- rdi_num++;
- else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_2PD)
- ppp_num++;
- else
- ipp_num++;
+ if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) {
+ ife_rd_num++;
+ } else {
+ for (i = 0; i < in_port->num_out_res; i++) {
+ out_port = &in_port->data[i];
+ if (cam_ife_hw_mgr_is_rdi_res(out_port->res_type))
+ rdi_num++;
+ else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_2PD)
+ ppp_num++;
+ else {
+ CAM_DBG(CAM_ISP, "out_res_type %d",
+ out_port->res_type);
+ ipp_num++;
+ }
+ }
}
*ipp_count = ipp_num;
*rdi_count = rdi_num;
*ppp_count = ppp_num;
+ *ife_rd_count = ife_rd_num;
+
+ CAM_DBG(CAM_ISP, "rdi: %d ipp: %d ppp: %d ife_rd: %d",
+ rdi_num, ipp_num, ppp_num, ife_rd_num);
return 0;
}
@@ -1450,6 +1771,7 @@ static int cam_ife_mgr_acquire_hw_for_ctx(
int ipp_count = 0;
int rdi_count = 0;
int ppp_count = 0;
+ int ife_rd_count = 0;
is_dual_vfe = in_port->usage_type;
@@ -1460,11 +1782,11 @@ static int cam_ife_mgr_acquire_hw_for_ctx(
goto err;
}
- cam_ife_hw_mgr_preprocess_out_port(ife_ctx, in_port,
- &ipp_count, &rdi_count, &ppp_count);
+ cam_ife_hw_mgr_preprocess_port(ife_ctx, in_port,
+ &ipp_count, &rdi_count, &ppp_count, &ife_rd_count);
- if (!ipp_count && !rdi_count && !ppp_count) {
- CAM_ERR(CAM_ISP, "No PIX or RDI or PPP resource");
+ if (!ipp_count && !rdi_count && !ppp_count && !ife_rd_count) {
+ CAM_ERR(CAM_ISP, "No PIX or RDI or PPP or IFE RD resource");
return -EINVAL;
}
@@ -1502,19 +1824,26 @@ static int cam_ife_mgr_acquire_hw_for_ctx(
/* get ife src resource */
- rc = cam_ife_hw_mgr_acquire_res_ife_src(ife_ctx, in_port);
+ if (ife_rd_count) {
+ rc = cam_ife_hw_mgr_acquire_res_ife_rd_src(ife_ctx, in_port);
+ rc = cam_ife_hw_mgr_acquire_res_bus_rd(ife_ctx, in_port);
+ } else {
+ rc = cam_ife_hw_mgr_acquire_res_ife_src(ife_ctx, in_port);
+ }
+
if (rc) {
CAM_ERR(CAM_ISP, "Acquire IFE SRC resource Failed");
goto err;
}
+ CAM_DBG(CAM_ISP, "Acquiring IFE OUT resource...");
rc = cam_ife_hw_mgr_acquire_res_ife_out(ife_ctx, in_port);
if (rc) {
CAM_ERR(CAM_ISP, "Acquire IFE OUT resource Failed");
goto err;
}
- *num_pix_port += ipp_count + ppp_count;
+ *num_pix_port += ipp_count + ppp_count + ife_rd_count;
*num_rdi_port += rdi_count;
return 0;
@@ -1538,8 +1867,8 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata,
if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) {
complete(&ctx->config_done_complete);
CAM_DBG(CAM_ISP,
- "Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu",
- handle, userdata, status, cookie);
+ "Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d",
+ handle, userdata, status, cookie, ctx->ctx_index);
} else {
CAM_WARN(CAM_ISP,
"Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu",
@@ -1618,8 +1947,22 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
((uint8_t *)&acquire_hw_info->data +
acquire_hw_info->input_info_offset);
+ rc = cam_ife_mgr_check_and_update_fe(ife_ctx, acquire_hw_info);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "buffer size is not enough");
+ goto free_ctx;
+ }
+
/* acquire HW resources */
for (i = 0; i < acquire_hw_info->num_inputs; i++) {
+
+ if (in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) {
+ CAM_ERR(CAM_ISP, "too many output res %d",
+ in_port->num_out_res);
+ rc = -EINVAL;
+ goto free_res;
+ }
+
in_port_length = sizeof(struct cam_isp_in_port_info) +
(in_port->num_out_res - 1) *
sizeof(struct cam_isp_out_port_info);
@@ -1630,6 +1973,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
rc = -EINVAL;
goto free_res;
}
+ CAM_DBG(CAM_ISP, "in_res_type %x", in_port->res_type);
rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port,
&num_pix_port_per_in, &num_rdi_port_per_in);
total_pix_port += num_pix_port_per_in;
@@ -1745,6 +2089,8 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args)
if (isp_resource[i].resource_id != CAM_ISP_RES_ID_PORT)
continue;
+ CAM_DBG(CAM_ISP, "acquire no = %d total = %d", i,
+ acquire_args->num_acq);
CAM_DBG(CAM_ISP,
"start copy from user handle %lld with len = %d",
isp_resource[i].res_hdl,
@@ -1882,7 +2228,8 @@ static int cam_isp_blob_bw_update(
if (!hw_mgr_res->hw_res[i])
continue;
- if (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF)
+ if ((hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF)
+ || (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_RD))
if (i == CAM_ISP_HW_SPLIT_LEFT) {
if (camif_l_bw_updated)
continue;
@@ -2013,8 +2360,9 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
}
}
- CAM_DBG(CAM_ISP, "Enter ctx id:%d num_hw_upd_entries %d",
- ctx->ctx_index, cfg->num_hw_update_entries);
+ CAM_DBG(CAM_ISP,
+ "Enter ctx id:%d num_hw_upd_entries %d request id: %llu",
+ ctx->ctx_index, cfg->num_hw_update_entries, cfg->request_id);
if (cfg->num_hw_update_entries > 0) {
cdm_cmd = ctx->cdm_cmd;
@@ -2047,21 +2395,21 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
msecs_to_jiffies(30));
if (rc <= 0) {
CAM_ERR(CAM_ISP,
- "config done completion timeout for req_id=%llu rc = %d",
- cfg->request_id, rc);
+ "config done completion timeout for req_id=%llu rc=%d ctx_index %d",
+ cfg->request_id, rc, ctx->ctx_index);
if (rc == 0)
rc = -ETIMEDOUT;
} else {
rc = 0;
CAM_DBG(CAM_ISP,
- "config done Success for req_id=%llu",
- cfg->request_id);
+ "config done Success for req_id=%llu ctx_index %d",
+ cfg->request_id, ctx->ctx_index);
}
}
} else {
CAM_ERR(CAM_ISP, "No commands to config");
}
- CAM_DBG(CAM_ISP, "Exit");
+ CAM_DBG(CAM_ISP, "Exit: Config Done: %llu", cfg->request_id);
return rc;
}
@@ -2134,6 +2482,11 @@ static int cam_ife_mgr_stop_hw_in_overflow(void *stop_hw_args)
cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
}
+ /* IFE bus rd resources */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+ cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
+ }
+
/* IFE out resources */
for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
cam_ife_hw_mgr_stop_hw_res(&ctx->res_list_ife_out[i]);
@@ -2236,11 +2589,6 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args)
CAM_DBG(CAM_ISP, "Halting CSIDs");
- CAM_DBG(CAM_ISP, "Going to stop IFE Out");
-
- /* IFE out resources */
- for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
- cam_ife_hw_mgr_stop_hw_res(&ctx->res_list_ife_out[i]);
/* get master base index first */
for (i = 0; i < ctx->num_base; i++) {
if (ctx->base[i].split_id == CAM_ISP_HW_SPLIT_LEFT) {
@@ -2249,15 +2597,6 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args)
}
}
- CAM_DBG(CAM_ISP, "Going to stop IFE Mux");
-
- /* IFE mux in resources */
- list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
- cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
- }
-
- cam_tasklet_stop(ctx->common.tasklet_info);
-
/*
* If Context does not have PIX resources and has only RDI resource
* then take the first base index.
@@ -2297,6 +2636,26 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args)
ctx->base[i].idx, csid_halt_type);
}
+ CAM_DBG(CAM_ISP, "Going to stop IFE Out");
+
+ /* IFE out resources */
+ for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
+ cam_ife_hw_mgr_stop_hw_res(&ctx->res_list_ife_out[i]);
+
+ /* IFE bus rd resources */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+ cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
+ }
+
+ CAM_DBG(CAM_ISP, "Going to stop IFE Mux");
+
+ /* IFE mux in resources */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+ cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
+ }
+
+ cam_tasklet_stop(ctx->common.tasklet_info);
+
cam_ife_mgr_pause_hw(ctx);
if (stop_isp->stop_only)
@@ -2386,6 +2745,17 @@ static int cam_ife_mgr_restart_hw(void *start_hw_args)
}
CAM_DBG(CAM_ISP, "START IFE SRC ... in ctx id:%d", ctx->ctx_index);
+
+ /* Start IFE BUS RD device */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+ rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Can not start IFE BUS RD (%d)",
+ hw_mgr_res->res_id);
+ goto err;
+ }
+ }
+
/* Start the IFE mux in devices */
list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
@@ -2536,6 +2906,18 @@ start_only:
}
}
+ CAM_DBG(CAM_ISP, "START IFE BUS RD ... in ctx id:%d",
+ ctx->ctx_index);
+ /* Start the IFE mux in devices */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+ rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Can not start IFE BUS RD (%d)",
+ hw_mgr_res->res_id);
+ goto err;
+ }
+ }
+
CAM_DBG(CAM_ISP, "START IFE SRC ... in ctx id:%d",
ctx->ctx_index);
/* Start the IFE mux in devices */
@@ -2595,7 +2977,6 @@ safe_disable:
deinit_hw:
cam_ife_hw_mgr_deinit_hw(ctx);
- ctx->init_done = false;
tasklet_stop:
cam_tasklet_stop(ctx->common.tasklet_info);
@@ -2667,6 +3048,78 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv,
return rc;
}
+static int cam_isp_blob_fe_update(
+ uint32_t blob_type,
+ struct cam_isp_generic_blob_info *blob_info,
+ struct cam_fe_config *fe_config,
+ struct cam_hw_prepare_update_args *prepare)
+{
+ struct cam_ife_hw_mgr_ctx *ctx = NULL;
+ struct cam_ife_hw_mgr_res *hw_mgr_res;
+ struct cam_hw_intf *hw_intf;
+ int rc = -EINVAL;
+ uint32_t i;
+ struct cam_vfe_fe_update_args fe_upd_args;
+
+ ctx = prepare->ctxt_to_hw_map;
+
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+ for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+ if (!hw_mgr_res->hw_res[i])
+ continue;
+
+ hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
+ if (hw_intf && hw_intf->hw_ops.process_cmd) {
+ fe_upd_args.node_res =
+ hw_mgr_res->hw_res[i];
+
+ memcpy(&fe_upd_args.fe_config, fe_config,
+ sizeof(struct cam_fe_config));
+
+ rc = hw_intf->hw_ops.process_cmd(
+ hw_intf->hw_priv,
+ CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD,
+ &fe_upd_args,
+ sizeof(
+ struct cam_fe_config));
+ if (rc)
+ CAM_ERR(CAM_ISP, "fs Update failed");
+ } else
+ CAM_WARN(CAM_ISP, "NULL hw_intf!");
+ }
+ }
+
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+ for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+ if (!hw_mgr_res->hw_res[i])
+ continue;
+
+ if (hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_RD)
+ continue;
+
+ hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
+ if (hw_intf && hw_intf->hw_ops.process_cmd) {
+ fe_upd_args.node_res =
+ hw_mgr_res->hw_res[i];
+
+ memcpy(&fe_upd_args.fe_config, fe_config,
+ sizeof(struct cam_fe_config));
+
+ rc = hw_intf->hw_ops.process_cmd(
+ hw_intf->hw_priv,
+ CAM_ISP_HW_CMD_FE_UPDATE_IN_RD,
+ &fe_upd_args,
+ sizeof(
+ struct cam_vfe_fe_update_args));
+ if (rc)
+ CAM_ERR(CAM_ISP, "fe Update failed");
+ } else
+ CAM_WARN(CAM_ISP, "NULL hw_intf!");
+ }
+ }
+ return rc;
+}
+
static int cam_isp_blob_ubwc_update(
uint32_t blob_type,
struct cam_isp_generic_blob_info *blob_info,
@@ -3004,7 +3457,7 @@ static int cam_isp_blob_clock_update(
camif_r_clk_updated = true;
}
} else if ((hw_mgr_res->res_id >=
- CAM_ISP_HW_VFE_IN_RDI0) && (hw_mgr_res->res_id
+ CAM_ISP_HW_VFE_IN_RD) && (hw_mgr_res->res_id
<= CAM_ISP_HW_VFE_IN_RDI3))
for (j = 0; j < clock_config->num_rdi; j++)
clk_rate = max(clock_config->rdi_hz[j],
@@ -3043,6 +3496,53 @@ static int cam_isp_blob_clock_update(
return rc;
}
+void fill_res_bitmap(uint32_t resource_type, unsigned long *res_bitmap)
+{
+
+ switch (resource_type) {
+ case CAM_ISP_IFE_OUT_RES_FULL:
+ case CAM_ISP_IFE_OUT_RES_DS4:
+ case CAM_ISP_IFE_OUT_RES_DS16:
+ case CAM_ISP_IFE_OUT_RES_RAW_DUMP:
+ case CAM_ISP_IFE_OUT_RES_FD:
+ case CAM_ISP_IFE_OUT_RES_PDAF:
+ case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE:
+ case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST:
+ case CAM_ISP_IFE_OUT_RES_STATS_TL_BG:
+ case CAM_ISP_IFE_OUT_RES_STATS_BF:
+ case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG:
+ case CAM_ISP_IFE_OUT_RES_STATS_BHIST:
+ case CAM_ISP_IFE_OUT_RES_STATS_RS:
+ case CAM_ISP_IFE_OUT_RES_STATS_CS:
+ case CAM_ISP_IFE_OUT_RES_STATS_IHIST:
+ case CAM_ISP_IFE_OUT_RES_FULL_DISP:
+ case CAM_ISP_IFE_OUT_RES_DS4_DISP:
+ case CAM_ISP_IFE_OUT_RES_DS16_DISP:
+ case CAM_ISP_IFE_IN_RES_RD:
+ set_bit(CAM_IFE_REG_UPD_CMD_PIX_BIT, res_bitmap);
+ break;
+ case CAM_ISP_IFE_OUT_RES_RDI_0:
+ set_bit(CAM_IFE_REG_UPD_CMD_RDI0_BIT, res_bitmap);
+ break;
+ case CAM_ISP_IFE_OUT_RES_RDI_1:
+ set_bit(CAM_IFE_REG_UPD_CMD_RDI1_BIT, res_bitmap);
+ break;
+ case CAM_ISP_IFE_OUT_RES_RDI_2:
+ set_bit(CAM_IFE_REG_UPD_CMD_RDI2_BIT, res_bitmap);
+ break;
+ case CAM_ISP_IFE_OUT_RES_RDI_3:
+ set_bit(CAM_IFE_REG_UPD_CMD_RDI3_BIT, res_bitmap);
+ break;
+ case CAM_ISP_IFE_OUT_RES_2PD:
+ set_bit(CAM_IFE_REG_UPD_CMD_DUAL_PD_BIT,
+ res_bitmap);
+ break;
+ default:
+ CAM_ERR(CAM_ISP, "Invalid resource");
+ break;
+ }
+}
+
static int cam_isp_packet_generic_blob_handler(void *user_data,
uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data)
{
@@ -3069,6 +3569,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
return -EINVAL;
}
+ CAM_DBG(CAM_ISP, "FS2: BLOB Type: %d", blob_type);
switch (blob_type) {
case CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG: {
struct cam_isp_resource_hfr_config *hfr_config =
@@ -3131,6 +3632,16 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
CAM_ERR(CAM_ISP, "Clock Update Failed");
}
break;
+ case CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG: {
+ struct cam_fe_config *fe_config =
+ (struct cam_fe_config *)blob_data;
+ rc = cam_isp_blob_fe_update(blob_type, blob_info,
+ fe_config, prepare);
+ if (rc)
+ CAM_ERR(CAM_ISP, "FS Update Failed rc: %d", rc);
+ }
+ break;
+
default:
CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type);
break;
@@ -3166,7 +3677,8 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
ctx = (struct cam_ife_hw_mgr_ctx *) prepare->ctxt_to_hw_map;
hw_mgr = (struct cam_ife_hw_mgr *)hw_mgr_priv;
- rc = cam_packet_util_validate_packet(prepare->packet);
+ rc = cam_packet_util_validate_packet(prepare->packet,
+ prepare->remain_len);
if (rc)
return rc;
@@ -3227,7 +3739,10 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
hw_mgr->mgr_common.img_iommu_hdl_secure,
prepare, ctx->base[i].idx,
&kmd_buf, ctx->res_list_ife_out,
- CAM_IFE_HW_OUT_RES_MAX, fill_fence);
+ &ctx->res_list_ife_in_rd,
+ CAM_IFE_HW_OUT_RES_MAX, fill_fence,
+ &ctx->res_bitmap,
+ fill_res_bitmap);
if (rc) {
CAM_ERR(CAM_ISP,
@@ -3268,7 +3783,8 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
/*Add reg update */
rc = cam_isp_add_reg_update(prepare, &ctx->res_list_ife_src,
- ctx->base[i].idx, &kmd_buf);
+ ctx->base[i].idx, &kmd_buf, ctx->is_fe_enable,
+ ctx->res_bitmap);
if (rc) {
CAM_ERR(CAM_ISP,
"Add Reg_update cmd Failed i=%d, idx=%d, rc=%d",
@@ -3276,6 +3792,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
goto end;
}
}
+ ctx->res_bitmap = 0;
end:
return rc;
@@ -3356,7 +3873,8 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet,
if (!io_cfg[i].mem_handle[j])
break;
- if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) ==
+ if (pf_buf_info &&
+ GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) ==
GET_FD_FROM_HANDLE(pf_buf_info)) {
CAM_INFO(CAM_ISP,
"Found PF at port: 0x%x mem 0x%x fd: 0x%x",
@@ -3391,9 +3909,10 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet,
}
CAM_INFO(CAM_ISP,
- "pln %d w %d h %d s 0x%x addr 0x%x end_addr 0x%x offset %x memh %x",
+ "pln %d w %d h %d s %u size 0x%x addr 0x%x end_addr 0x%x offset %x memh %x",
j, io_cfg[i].planes[j].width,
io_cfg[i].planes[j].height,
+ io_cfg[i].planes[j].plane_stride,
(unsigned int)src_buf_size,
(unsigned int)iova_addr,
(unsigned int)iova_addr +
@@ -3434,12 +3953,6 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
hw_cmd_args->u.internal_args;
switch (isp_hw_cmd_args->cmd_type) {
- case CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT:
- if (ctx->is_rdi_only_context)
- isp_hw_cmd_args->u.is_rdi_only_context = 1;
- else
- isp_hw_cmd_args->u.is_rdi_only_context = 0;
- break;
case CAM_ISP_HW_MGR_CMD_PAUSE_HW:
cam_ife_mgr_pause_hw(ctx);
break;
@@ -3450,6 +3963,14 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
cam_ife_mgr_sof_irq_debug(ctx,
isp_hw_cmd_args->u.sof_irq_enable);
break;
+ case CAM_ISP_HW_MGR_CMD_CTX_TYPE:
+ if (ctx->is_fe_enable)
+ isp_hw_cmd_args->u.ctx_type = CAM_ISP_CTX_FS2;
+ else if (ctx->is_rdi_only_context)
+ isp_hw_cmd_args->u.ctx_type = CAM_ISP_CTX_RDI;
+ else
+ isp_hw_cmd_args->u.ctx_type = CAM_ISP_CTX_PIX;
+ break;
default:
CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x",
hw_cmd_args->cmd_type);
@@ -3485,17 +4006,25 @@ static int cam_ife_mgr_cmd_get_sof_timestamp(
list_for_each_entry(hw_mgr_res, &ife_ctx->res_list_ife_csid, list) {
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
- if (!hw_mgr_res->hw_res[i] ||
- (i == CAM_ISP_HW_SPLIT_RIGHT))
+ if (!hw_mgr_res->hw_res[i])
continue;
+
/*
* Get the SOF time stamp from left resource only.
* Left resource is master for dual vfe case and
* Rdi only context case left resource only hold
* the RDI resource
*/
+
hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
if (hw_intf->hw_ops.process_cmd) {
+ /*
+ * Single VFE case, Get the time stamp from
+ * available one csid hw in the context
+ * Dual VFE case, get the time stamp from
+ * master(left) would be sufficient
+ */
+
csid_get_time.node_res =
hw_mgr_res->hw_res[i];
rc = hw_intf->hw_ops.process_cmd(
@@ -3504,23 +4033,16 @@ static int cam_ife_mgr_cmd_get_sof_timestamp(
&csid_get_time,
sizeof(
struct cam_csid_get_time_stamp_args));
- if (!rc) {
+ if (!rc && (i == CAM_ISP_HW_SPLIT_LEFT)) {
*time_stamp =
csid_get_time.time_stamp_val;
*boot_time_stamp =
csid_get_time.boot_timestamp;
}
- /*
- * Single VFE case, Get the time stamp from available
- * one csid hw in the context
- * Dual VFE case, get the time stamp from master(left)
- * would be sufficient
- */
- goto end;
}
}
}
-end:
+
if (rc)
CAM_ERR(CAM_ISP, "Getting sof time stamp failed");
@@ -3790,6 +4312,8 @@ static int cam_ife_hw_mgr_get_err_type(
core_idx = evt_payload->core_index;
evt_payload->evt_id = CAM_ISP_HW_EVENT_ERROR;
+ evt_payload->enable_reg_dump =
+ g_ife_hw_mgr.debug_cfg.enable_reg_dump;
list_for_each_entry(isp_ife_camif_res,
&ife_hwr_mgr_ctx->res_list_ife_src, list) {
@@ -3860,23 +4384,26 @@ static int cam_ife_hw_mgr_handle_camif_error(
error_status = cam_ife_hw_mgr_get_err_type(ife_hwr_mgr_ctx,
evt_payload);
-
- if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending))
- return error_status;
+ if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending)) {
+ rc = error_status;
+ goto end;
+ }
switch (error_status) {
case CAM_ISP_HW_ERROR_OVERFLOW:
case CAM_ISP_HW_ERROR_P2I_ERROR:
case CAM_ISP_HW_ERROR_VIOLATION:
CAM_ERR(CAM_ISP, "Enter: error_type (%d)", error_status);
- rc = -EFAULT;
-
+ rc = error_status;
if (g_ife_hw_mgr.debug_cfg.enable_recovery)
error_event_data.recovery_enabled = true;
error_event_data.error_type =
CAM_ISP_HW_ERROR_OVERFLOW;
+ error_event_data.enable_reg_dump =
+ g_ife_hw_mgr.debug_cfg.enable_reg_dump;
+
cam_ife_hw_mgr_find_affected_ctx(ife_hwr_mgr_ctx,
&error_event_data,
core_idx,
@@ -3897,6 +4424,7 @@ static int cam_ife_hw_mgr_handle_camif_error(
break;
}
+end:
return rc;
}
@@ -3946,6 +4474,7 @@ static int cam_ife_hw_mgr_handle_reg_update(
case CAM_ISP_HW_VFE_IN_CAMIF_LITE:
break;
case CAM_ISP_HW_VFE_IN_CAMIF:
+ case CAM_ISP_HW_VFE_IN_RD:
if (ife_src_res->is_dual_vfe)
/* It checks for slave core RUP ACK*/
hw_res = ife_src_res->hw_res[1];
@@ -3999,7 +4528,8 @@ static int cam_ife_hw_mgr_handle_reg_update(
rup_status = hw_res->bottom_half_handler(
hw_res, evt_payload);
- if (!ife_hwr_mgr_ctx->is_rdi_only_context)
+ if (ife_hwr_mgr_ctx->is_rdi_only_context == 0 &&
+ ife_hwr_mgr_ctx->is_fe_enable == false)
continue;
if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending))
@@ -4106,9 +4636,10 @@ static int cam_ife_hw_mgr_handle_epoch_for_camif_hw_res(
list_for_each_entry(isp_ife_camif_res,
&ife_hwr_mgr_ctx->res_list_ife_src, list) {
if ((isp_ife_camif_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT)
- || (isp_ife_camif_res->res_id !=
- CAM_ISP_HW_VFE_IN_CAMIF))
+ || (isp_ife_camif_res->res_id >
+ CAM_ISP_HW_VFE_IN_RD)) {
continue;
+ }
hw_res_l = isp_ife_camif_res->hw_res[0];
hw_res_r = isp_ife_camif_res->hw_res[1];
@@ -4341,7 +4872,8 @@ static int cam_ife_hw_mgr_handle_sof(
hw_res, evt_payload);
/* check if it is rdi only context */
- if (ife_hw_mgr_ctx->is_rdi_only_context) {
+ if (ife_hw_mgr_ctx->is_fe_enable ||
+ ife_hw_mgr_ctx->is_rdi_only_context) {
if (!sof_status && !sof_sent) {
cam_ife_mgr_cmd_get_sof_timestamp(
ife_hw_mgr_ctx,
@@ -4352,7 +4884,7 @@ static int cam_ife_hw_mgr_handle_sof(
ife_hw_mgr_ctx->common.cb_priv,
CAM_ISP_HW_EVENT_SOF,
&sof_done_event_data);
- CAM_DBG(CAM_ISP, "sof_status = %d",
+ CAM_DBG(CAM_ISP, "RDI sof_status = %d",
sof_status);
sof_sent = true;
@@ -4362,6 +4894,7 @@ static int cam_ife_hw_mgr_handle_sof(
break;
case CAM_ISP_HW_VFE_IN_CAMIF:
+ case CAM_ISP_HW_VFE_IN_RD:
sof_status = cam_ife_hw_mgr_process_camif_sof(
ife_src_res, ife_hw_mgr_ctx, evt_payload);
if (!sof_status && !sof_sent) {
@@ -4832,6 +5365,14 @@ static int cam_ife_hw_mgr_debug_register(void)
return -ENOMEM;
}
+ if (!debugfs_create_u32("enable_reg_dump",
+ 0644,
+ g_ife_hw_mgr.debug_cfg.dentry,
+ &g_ife_hw_mgr.debug_cfg.enable_reg_dump)) {
+ CAM_ERR(CAM_ISP, "failed to create enable_reg_dump");
+ goto err;
+ }
+
if (!debugfs_create_file("ife_csid_debug",
0644,
g_ife_hw_mgr.debug_cfg.dentry, NULL,
@@ -4975,6 +5516,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl)
INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_cid);
INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_csid);
INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_src);
+ INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_in_rd);
ctx_pool = &g_ife_hw_mgr.ctx_pool[i];
for (j = 0; j < CAM_IFE_HW_OUT_RES_MAX; j++) {
res_list_ife_out = &ctx_pool->res_list_ife_out[j];
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
index cf1e425558f3..bf5f1527caa4 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -26,6 +26,7 @@ enum cam_ife_hw_mgr_res_type {
CAM_IFE_HW_MGR_RES_CID,
CAM_IFE_HW_MGR_RES_CSID,
CAM_IFE_HW_MGR_RES_IFE_SRC,
+ CAM_IFE_HW_MGR_RES_IFE_IN_RD,
CAM_IFE_HW_MGR_RES_IFE_OUT,
};
@@ -87,6 +88,7 @@ struct ctx_base_info {
* @csid_debug: csid debug information
* @enable_recovery: enable recovery
* @enable_diag_sensor_status: enable sensor diagnosis status
+ * @enable_reg_dump: enable register dump on error
*
*/
struct cam_ife_hw_mgr_debug {
@@ -94,6 +96,7 @@ struct cam_ife_hw_mgr_debug {
uint64_t csid_debug;
uint32_t enable_recovery;
uint32_t camif_debug;
+ uint32_t enable_reg_dump;
};
/**
@@ -108,6 +111,7 @@ struct cam_ife_hw_mgr_debug {
* one.
* @res_list_csid: CSID resource list
* @res_list_ife_src: IFE input resource list
+ * @res_list_ife_in_rd IFE input resource list for read path
* @res_list_ife_out: IFE output resoruces array
* @free_res_list: Free resources list for the branch node
* @res_pool: memory storage for the free resource list
@@ -128,6 +132,8 @@ struct cam_ife_hw_mgr_debug {
* @is_rdi_only_context flag to specify the context has only rdi resource
* @config_done_complete indicator for configuration complete
* @init_done indicate whether init hw is done
+ * @is_fe_enable indicate whether fetch engine\read path is enabled
+ * @res_bitmap fill resource bitmap for which rup to be set
*/
struct cam_ife_hw_mgr_ctx {
struct list_head list;
@@ -141,6 +147,7 @@ struct cam_ife_hw_mgr_ctx {
struct list_head res_list_ife_cid;
struct list_head res_list_ife_csid;
struct list_head res_list_ife_src;
+ struct list_head res_list_ife_in_rd;
struct cam_ife_hw_mgr_res res_list_ife_out[
CAM_IFE_HW_OUT_RES_MAX];
@@ -162,6 +169,8 @@ struct cam_ife_hw_mgr_ctx {
uint32_t is_rdi_only_context;
struct completion config_done_complete;
bool init_done;
+ bool is_fe_enable;
+ unsigned long res_bitmap;
};
/**
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
index cd1d024148ff..0b3c3874a704 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -105,7 +105,7 @@ static int cam_isp_update_dual_config(
struct cam_isp_hw_dual_isp_update_args dual_isp_update_args;
uint32_t outport_id;
uint32_t ports_plane_idx;
- size_t len = 0;
+ size_t len = 0, remain_len = 0;
uint32_t *cpu_addr;
uint32_t i, j;
@@ -117,9 +117,22 @@ static int cam_isp_update_dual_config(
if (rc)
return rc;
+ if ((len < sizeof(struct cam_isp_dual_config)) ||
+ (cmd_desc->offset >=
+ (len - sizeof(struct cam_isp_dual_config)))) {
+ CAM_ERR(CAM_UTIL, "not enough buffer provided");
+ return -EINVAL;
+ }
+ remain_len = len - cmd_desc->offset;
cpu_addr += (cmd_desc->offset / 4);
dual_config = (struct cam_isp_dual_config *)cpu_addr;
+ if ((dual_config->num_ports *
+ sizeof(struct cam_isp_dual_stripe_config)) >
+ (remain_len - offsetof(struct cam_isp_dual_config, stripes))) {
+ CAM_ERR(CAM_UTIL, "not enough buffer for all the dual configs");
+ return -EINVAL;
+ }
for (i = 0; i < dual_config->num_ports; i++) {
if (i >= CAM_ISP_IFE_OUT_RES_MAX) {
@@ -430,8 +443,11 @@ int cam_isp_add_io_buffers(
uint32_t base_idx,
struct cam_kmd_buf_info *kmd_buf_info,
struct cam_ife_hw_mgr_res *res_list_isp_out,
+ struct list_head *res_list_ife_in_rd,
uint32_t size_isp_out,
- bool fill_fence)
+ bool fill_fence,
+ unsigned long *res_bitmap,
+ cam_fill_res_bitmap fill_res_bitmap)
{
int rc = 0;
uint64_t io_addr[CAM_PACKET_MAX_PLANES];
@@ -440,6 +456,7 @@ int cam_isp_add_io_buffers(
struct cam_ife_hw_mgr_res *hw_mgr_res;
struct cam_isp_hw_get_cmd_update update_buf;
struct cam_isp_hw_get_wm_update wm_update;
+ struct cam_isp_hw_get_wm_update bus_rd_update;
struct cam_hw_fence_map_entry *out_map_entries;
struct cam_hw_fence_map_entry *in_map_entries;
uint32_t kmd_buf_remain_size;
@@ -517,6 +534,15 @@ int cam_isp_add_io_buffers(
CAM_DBG(CAM_ISP,
"configure input io with fill fence %d",
fill_fence);
+ if (!list_empty(res_list_ife_in_rd)) {
+ hw_mgr_res =
+ list_first_entry(res_list_ife_in_rd,
+ struct cam_ife_hw_mgr_res, list);
+ } else {
+ CAM_ERR(CAM_ISP,
+ "No IFE in Read resource");
+ return -EINVAL;
+ }
in_map_entries =
&prepare->in_map_entries[num_in_buf];
if (fill_fence) {
@@ -533,7 +559,6 @@ int cam_isp_add_io_buffers(
return -EINVAL;
}
}
- continue;
} else {
CAM_ERR(CAM_ISP, "Invalid io config direction :%d",
io_cfg[i].direction);
@@ -541,7 +566,8 @@ int cam_isp_add_io_buffers(
}
CAM_DBG(CAM_ISP, "setup mem io");
- for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) {
+ for (j = 0; j < CAM_ISP_HW_SPLIT_MAX &&
+ io_cfg[i].direction == CAM_BUF_OUTPUT; j++) {
if (!hw_mgr_res->hw_res[j])
continue;
@@ -656,6 +682,118 @@ int cam_isp_add_io_buffers(
}
io_cfg_used_bytes += update_buf.cmd.used_bytes;
}
+ for (j = 0; j < CAM_ISP_HW_SPLIT_MAX &&
+ io_cfg[i].direction == CAM_BUF_INPUT; j++) {
+ if (!hw_mgr_res->hw_res[j])
+ continue;
+
+ if (hw_mgr_res->hw_res[j]->hw_intf->hw_idx != base_idx)
+ continue;
+
+ res = hw_mgr_res->hw_res[j];
+
+ memset(io_addr, 0, sizeof(io_addr));
+
+ for (plane_id = 0; plane_id < CAM_PACKET_MAX_PLANES;
+ plane_id++) {
+ if (!io_cfg[i].mem_handle[plane_id])
+ break;
+
+ hdl = io_cfg[i].mem_handle[plane_id];
+ if (res->process_cmd(res,
+ CAM_ISP_HW_CMD_GET_SECURE_MODE,
+ &mode,
+ sizeof(bool)))
+ return -EINVAL;
+
+ is_buf_secure = cam_mem_is_secure_buf(hdl);
+ if ((mode == CAM_SECURE_MODE_SECURE) &&
+ is_buf_secure) {
+ mmu_hdl = sec_iommu_hdl;
+ } else if (
+ (mode == CAM_SECURE_MODE_NON_SECURE) &&
+ (!is_buf_secure)) {
+ mmu_hdl = iommu_hdl;
+ } else {
+ CAM_ERR_RATE_LIMIT(CAM_ISP,
+ "Invalid hdl: port mode[%u], buf mode[%u]",
+ mode, is_buf_secure);
+ return -EINVAL;
+ }
+
+ rc = cam_mem_get_io_buf(
+ io_cfg[i].mem_handle[plane_id],
+ mmu_hdl, &io_addr[plane_id], &size);
+ if (rc) {
+ CAM_ERR(CAM_ISP,
+ "no io addr for plane%d",
+ plane_id);
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ /* need to update with offset */
+ io_addr[plane_id] +=
+ io_cfg[i].offsets[plane_id];
+ CAM_DBG(CAM_ISP,
+ "get io_addr for plane %d: 0x%llx, mem_hdl=0x%x",
+ plane_id, io_addr[plane_id],
+ io_cfg[i].mem_handle[plane_id]);
+
+ CAM_DBG(CAM_ISP,
+ "mmu_hdl=0x%x, size=%d, end=0x%x",
+ mmu_hdl, (int)size,
+ io_addr[plane_id]+size);
+
+ }
+ if (!plane_id) {
+ CAM_ERR(CAM_ISP, "No valid planes for res%d",
+ res->res_id);
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ if ((kmd_buf_info->used_bytes + io_cfg_used_bytes) <
+ kmd_buf_info->size) {
+ kmd_buf_remain_size = kmd_buf_info->size -
+ (kmd_buf_info->used_bytes +
+ io_cfg_used_bytes);
+ } else {
+ CAM_ERR(CAM_ISP,
+ "no free kmd memory for base %d",
+ base_idx);
+ rc = -ENOMEM;
+ return rc;
+ }
+ update_buf.res = res;
+ update_buf.cmd_type = CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM;
+ update_buf.cmd.cmd_buf_addr = kmd_buf_info->cpu_addr +
+ kmd_buf_info->used_bytes/4 +
+ io_cfg_used_bytes/4;
+ bus_rd_update.image_buf = io_addr;
+ bus_rd_update.num_buf = plane_id;
+ bus_rd_update.io_cfg = &io_cfg[i];
+ update_buf.cmd.size = kmd_buf_remain_size;
+ update_buf.rm_update = &bus_rd_update;
+
+ CAM_DBG(CAM_ISP, "cmd buffer 0x%pK, size %d",
+ update_buf.cmd.cmd_buf_addr,
+ update_buf.cmd.size);
+ rc = res->hw_intf->hw_ops.process_cmd(
+ res->hw_intf->hw_priv,
+ CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM, &update_buf,
+ sizeof(struct cam_isp_hw_get_cmd_update));
+
+ if (rc) {
+ CAM_ERR(CAM_ISP, "get buf cmd error:%d",
+ res->res_id);
+ rc = -ENOMEM;
+ return rc;
+ }
+ io_cfg_used_bytes += update_buf.cmd.used_bytes;
+ }
+
+ fill_res_bitmap(io_cfg[i].resource_type, res_bitmap);
}
CAM_DBG(CAM_ISP, "io_cfg_used_bytes %d, fill_fence %d",
@@ -694,13 +832,16 @@ int cam_isp_add_reg_update(
struct cam_hw_prepare_update_args *prepare,
struct list_head *res_list_isp_src,
uint32_t base_idx,
- struct cam_kmd_buf_info *kmd_buf_info)
+ struct cam_kmd_buf_info *kmd_buf_info,
+ bool is_fe_en,
+ unsigned long res_bitmap)
{
int rc = -EINVAL;
struct cam_isp_resource_node *res;
struct cam_ife_hw_mgr_res *hw_mgr_res;
struct cam_hw_update_entry *hw_entry;
struct cam_isp_hw_get_cmd_update get_regup;
+ struct cam_isp_hw_rup_data rup_data;
uint32_t kmd_buf_remain_size, num_ent, i, reg_update_size;
hw_entry = prepare->hw_update_entries;
@@ -746,6 +887,9 @@ int cam_isp_add_reg_update(
get_regup.cmd.size = kmd_buf_remain_size;
get_regup.cmd_type = CAM_ISP_HW_CMD_GET_REG_UPDATE;
get_regup.res = res;
+ rup_data.is_fe_enable = is_fe_en;
+ rup_data.res_bitmap = res_bitmap;
+ get_regup.rup_data = &rup_data;
rc = res->hw_intf->hw_ops.process_cmd(
res->hw_intf->hw_priv,
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h
index 9c1caa03e06c..806c2c657165 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -123,8 +123,11 @@ int cam_isp_add_command_buffers(
* @base_idx: Base or dev index of the IFE/VFE HW instance
* @kmd_buf_info: Kmd buffer to store the change base command
* @res_list_isp_out: IFE /VFE out resource list
+ * @res_list_ife_in_rd: IFE /VFE in rd resource list
* @size_isp_out: Size of the res_list_isp_out array
* @fill_fence: If true, Fence map table will be filled
+ * @res_bitmap resource bitmap to be set for rup
+ * @fill_res_bitmap callback function to set resource bitmap
*
* @return: 0 for success
* -EINVAL for Fail
@@ -136,8 +139,11 @@ int cam_isp_add_io_buffers(
uint32_t base_idx,
struct cam_kmd_buf_info *kmd_buf_info,
struct cam_ife_hw_mgr_res *res_list_isp_out,
+ struct list_head *res_list_ife_in_rd,
uint32_t size_isp_out,
- bool fill_fence);
+ bool fill_fence,
+ unsigned long *res_bitmap,
+ cam_fill_res_bitmap fill_res_bitmap);
/*
* cam_isp_add_reg_update()
@@ -150,6 +156,9 @@ int cam_isp_add_io_buffers(
* @res_list_isp_src: Resource list for IFE/VFE source
* @base_idx: Base or dev index of the IFE/VFE HW instance
* @kmd_buf_info: Kmd buffer to store the change base command
+ * @is_fe_enable If fetch engine enable
+ * @res_bitmap resource bitmap to be set for rup
+ *
* @return: 0 for success
* -EINVAL for Fail
*/
@@ -157,6 +166,8 @@ int cam_isp_add_reg_update(
struct cam_hw_prepare_update_args *prepare,
struct list_head *res_list_isp_src,
uint32_t base_idx,
- struct cam_kmd_buf_info *kmd_buf_info);
+ struct cam_kmd_buf_info *kmd_buf_info,
+ bool is_fe_enable,
+ unsigned long res_bitmap);
#endif /*_CAM_ISP_HW_PARSER_H */
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
index e418fa97081d..c5808d45b0b1 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -617,7 +617,7 @@ static void cam_irq_controller_th_processing(
evt_handler->bottom_half, &bh_cmd);
if (rc || !bh_cmd) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
- "Can't get bh payload");
+ "No payload, IRQ handling frozen");
continue;
}
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
index 1a0f1ecab7b6..e9bcc98a8956 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, 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
@@ -19,6 +19,16 @@
#include <uapi/media/cam_isp.h>
#include "cam_hw_mgr_intf.h"
+/*
+ * bit position in resource bitmap
+ */
+#define CAM_IFE_REG_UPD_CMD_PIX_BIT 0
+#define CAM_IFE_REG_UPD_CMD_RDI0_BIT 1
+#define CAM_IFE_REG_UPD_CMD_RDI1_BIT 2
+#define CAM_IFE_REG_UPD_CMD_RDI2_BIT 3
+#define CAM_IFE_REG_UPD_CMD_RDI3_BIT 4
+#define CAM_IFE_REG_UPD_CMD_DUAL_PD_BIT 5
+
/* MAX IFE instance */
#define CAM_IFE_HW_NUM_MAX 4
#define CAM_IFE_RDI_NUM_MAX 4
@@ -186,11 +196,13 @@ struct cam_isp_hw_eof_event_data {
* @timestamp: Timestamp for the error event
* @recovery_enabled: Identifies if the context needs to recover & reapply
* this request
+ * @enable_reg_dump: enable register dump
*/
struct cam_isp_hw_error_event_data {
uint32_t error_type;
uint64_t timestamp;
bool recovery_enabled;
+ bool enable_reg_dump;
};
/* enum cam_isp_hw_mgr_command - Hardware manager command type */
@@ -199,20 +211,28 @@ enum cam_isp_hw_mgr_command {
CAM_ISP_HW_MGR_CMD_PAUSE_HW,
CAM_ISP_HW_MGR_CMD_RESUME_HW,
CAM_ISP_HW_MGR_CMD_SOF_DEBUG,
+ CAM_ISP_HW_MGR_CMD_CTX_TYPE,
CAM_ISP_HW_MGR_CMD_MAX,
};
+enum cam_isp_ctx_type {
+ CAM_ISP_CTX_FS2 = 1,
+ CAM_ISP_CTX_RDI,
+ CAM_ISP_CTX_PIX,
+ CAM_ISP_CTX_MAX,
+};
/**
* struct cam_isp_hw_cmd_args - Payload for hw manager command
*
* @cmd_type HW command type
- * @get_context Get context type information
+ * @sof_irq_enable To debug if SOF irq is enabled
+ * @ctx_type RDI_ONLY, PIX and RDI, or FS2
*/
struct cam_isp_hw_cmd_args {
- uint32_t cmd_type;
+ uint32_t cmd_type;
union {
- uint32_t is_rdi_only_context;
uint32_t sof_irq_enable;
+ uint32_t ctx_type;
} u;
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.c
deleted file mode 100644
index 70223f1427f5..000000000000
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-
-#include <linux/module.h>
-#include "cam_ife_csid_core.h"
-#include "cam_ife_csid170.h"
-#include "cam_ife_csid_dev.h"
-
-#define CAM_CSID_DRV_NAME "csid_170"
-#define CAM_CSID_VERSION_V170 0x10070000
-
-static struct cam_ife_csid_hw_info cam_ife_csid170_hw_info = {
- .csid_reg = &cam_ife_csid_170_reg_offset,
- .hw_dts_version = CAM_CSID_VERSION_V170,
-};
-
-static const struct of_device_id cam_ife_csid170_dt_match[] = {
- {
- .compatible = "qcom,csid170",
- .data = &cam_ife_csid170_hw_info,
- },
- {}
-};
-
-MODULE_DEVICE_TABLE(of, cam_ife_csid170_dt_match);
-
-static struct platform_driver cam_ife_csid170_driver = {
- .probe = cam_ife_csid_probe,
- .remove = cam_ife_csid_remove,
- .driver = {
- .name = CAM_CSID_DRV_NAME,
- .owner = THIS_MODULE,
- .of_match_table = cam_ife_csid170_dt_match,
- .suppress_bind_attrs = true,
- },
-};
-
-static int __init cam_ife_csid170_init_module(void)
-{
- return platform_driver_register(&cam_ife_csid170_driver);
-}
-
-static void __exit cam_ife_csid170_exit_module(void)
-{
- platform_driver_unregister(&cam_ife_csid170_driver);
-}
-
-module_init(cam_ife_csid170_init_module);
-module_exit(cam_ife_csid170_exit_module);
-MODULE_DESCRIPTION("CAM IFE_CSID170 driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h
index 85fec0f15dcd..576e8cb8d3b8 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -222,6 +222,7 @@ static struct cam_ife_csid_csi2_rx_reg_offset
.csi2_capture_short_pkt_vc_shift = 15,
.csi2_capture_cphy_pkt_dt_shift = 20,
.csi2_capture_cphy_pkt_vc_shift = 26,
+ .csi2_rx_phy_num_mask = 0x3,
};
static struct cam_ife_csid_csi2_tpg_reg_offset
@@ -273,6 +274,7 @@ static struct cam_ife_csid_common_reg_offset
.num_rdis = 3,
.num_pix = 1,
.num_ppp = 0,
+ .csid_reg_rst_stb = 1,
.csid_rst_stb = 0x1e,
.csid_rst_stb_sw_all = 0x1f,
.path_rst_stb_all = 0x7f,
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h
index 4fdc518c0385..42f0f290a166 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -10,56 +10,93 @@
* GNU General Public License for more details.
*/
-#ifndef _CAM_IFE_CSID_LITE170_H_
-#define _CAM_IFE_CSID_LITE170_H_
+#ifndef _CAM_IFE_CSID_175_H_
+#define _CAM_IFE_CSID_175_H_
+
#include "cam_ife_csid_core.h"
-static struct cam_ife_csid_rdi_reg_offset
- cam_ife_csid_lite_170_rdi_0_reg_offset = {
+static struct cam_ife_csid_pxl_reg_offset cam_ife_csid_175_ipp_reg_offset = {
+ .csid_pxl_irq_status_addr = 0x30,
+ .csid_pxl_irq_mask_addr = 0x34,
+ .csid_pxl_irq_clear_addr = 0x38,
+ .csid_pxl_irq_set_addr = 0x3c,
+
+ .csid_pxl_cfg0_addr = 0x200,
+ .csid_pxl_cfg1_addr = 0x204,
+ .csid_pxl_ctrl_addr = 0x208,
+ .csid_pxl_frm_drop_pattern_addr = 0x20c,
+ .csid_pxl_frm_drop_period_addr = 0x210,
+ .csid_pxl_irq_subsample_pattern_addr = 0x214,
+ .csid_pxl_irq_subsample_period_addr = 0x218,
+ .csid_pxl_hcrop_addr = 0x21c,
+ .csid_pxl_vcrop_addr = 0x220,
+ .csid_pxl_pix_drop_pattern_addr = 0x224,
+ .csid_pxl_pix_drop_period_addr = 0x228,
+ .csid_pxl_line_drop_pattern_addr = 0x22c,
+ .csid_pxl_line_drop_period_addr = 0x230,
+ .csid_pxl_rst_strobes_addr = 0x240,
+ .csid_pxl_status_addr = 0x254,
+ .csid_pxl_misr_val_addr = 0x258,
+ .csid_pxl_format_measure_cfg0_addr = 0x270,
+ .csid_pxl_format_measure_cfg1_addr = 0x274,
+ .csid_pxl_format_measure0_addr = 0x278,
+ .csid_pxl_format_measure1_addr = 0x27c,
+ .csid_pxl_format_measure2_addr = 0x280,
+ .csid_pxl_timestamp_curr0_sof_addr = 0x290,
+ .csid_pxl_timestamp_curr1_sof_addr = 0x294,
+ .csid_pxl_timestamp_perv0_sof_addr = 0x298,
+ .csid_pxl_timestamp_perv1_sof_addr = 0x29c,
+ .csid_pxl_timestamp_curr0_eof_addr = 0x2a0,
+ .csid_pxl_timestamp_curr1_eof_addr = 0x2a4,
+ .csid_pxl_timestamp_perv0_eof_addr = 0x2a8,
+ .csid_pxl_timestamp_perv1_eof_addr = 0x2ac,
+ /* configurations */
+ .pix_store_en_shift_val = 7,
+ .early_eof_en_shift_val = 29,
+};
+
+static struct cam_ife_csid_pxl_reg_offset cam_ife_csid_175_ppp_reg_offset = {
+ .csid_pxl_irq_status_addr = 0xa0,
+ .csid_pxl_irq_mask_addr = 0xa4,
+ .csid_pxl_irq_clear_addr = 0xa8,
+ .csid_pxl_irq_set_addr = 0xac,
- .csid_rdi_irq_status_addr = 0x30,
- .csid_rdi_irq_mask_addr = 0x34,
- .csid_rdi_irq_clear_addr = 0x38,
- .csid_rdi_irq_set_addr = 0x3c,
- .csid_rdi_cfg0_addr = 0x200,
- .csid_rdi_cfg1_addr = 0x204,
- .csid_rdi_ctrl_addr = 0x208,
- .csid_rdi_frm_drop_pattern_addr = 0x20c,
- .csid_rdi_frm_drop_period_addr = 0x210,
- .csid_rdi_irq_subsample_pattern_addr = 0x214,
- .csid_rdi_irq_subsample_period_addr = 0x218,
- .csid_rdi_rpp_hcrop_addr = 0x21c,
- .csid_rdi_rpp_vcrop_addr = 0x220,
- .csid_rdi_rpp_pix_drop_pattern_addr = 0x224,
- .csid_rdi_rpp_pix_drop_period_addr = 0x228,
- .csid_rdi_rpp_line_drop_pattern_addr = 0x22c,
- .csid_rdi_rpp_line_drop_period_addr = 0x230,
- .csid_rdi_rst_strobes_addr = 0x240,
- .csid_rdi_status_addr = 0x250,
- .csid_rdi_misr_val0_addr = 0x254,
- .csid_rdi_misr_val1_addr = 0x258,
- .csid_rdi_misr_val2_addr = 0x25c,
- .csid_rdi_misr_val3_addr = 0x260,
- .csid_rdi_format_measure_cfg0_addr = 0x270,
- .csid_rdi_format_measure_cfg1_addr = 0x274,
- .csid_rdi_format_measure0_addr = 0x278,
- .csid_rdi_format_measure1_addr = 0x27c,
- .csid_rdi_format_measure2_addr = 0x280,
- .csid_rdi_timestamp_curr0_sof_addr = 0x290,
- .csid_rdi_timestamp_curr1_sof_addr = 0x294,
- .csid_rdi_timestamp_prev0_sof_addr = 0x298,
- .csid_rdi_timestamp_prev1_sof_addr = 0x29c,
- .csid_rdi_timestamp_curr0_eof_addr = 0x2a0,
- .csid_rdi_timestamp_curr1_eof_addr = 0x2a4,
- .csid_rdi_timestamp_prev0_eof_addr = 0x2a8,
- .csid_rdi_timestamp_prev1_eof_addr = 0x2ac,
- .csid_rdi_byte_cntr_ping_addr = 0x2e0,
- .csid_rdi_byte_cntr_pong_addr = 0x2e4,
+ .csid_pxl_cfg0_addr = 0x700,
+ .csid_pxl_cfg1_addr = 0x704,
+ .csid_pxl_ctrl_addr = 0x708,
+ .csid_pxl_frm_drop_pattern_addr = 0x70c,
+ .csid_pxl_frm_drop_period_addr = 0x710,
+ .csid_pxl_irq_subsample_pattern_addr = 0x714,
+ .csid_pxl_irq_subsample_period_addr = 0x718,
+ .csid_pxl_hcrop_addr = 0x71c,
+ .csid_pxl_vcrop_addr = 0x720,
+ .csid_pxl_pix_drop_pattern_addr = 0x724,
+ .csid_pxl_pix_drop_period_addr = 0x728,
+ .csid_pxl_line_drop_pattern_addr = 0x72c,
+ .csid_pxl_line_drop_period_addr = 0x730,
+ .csid_pxl_rst_strobes_addr = 0x740,
+ .csid_pxl_status_addr = 0x754,
+ .csid_pxl_misr_val_addr = 0x758,
+ .csid_pxl_format_measure_cfg0_addr = 0x770,
+ .csid_pxl_format_measure_cfg1_addr = 0x774,
+ .csid_pxl_format_measure0_addr = 0x778,
+ .csid_pxl_format_measure1_addr = 0x77c,
+ .csid_pxl_format_measure2_addr = 0x780,
+ .csid_pxl_timestamp_curr0_sof_addr = 0x790,
+ .csid_pxl_timestamp_curr1_sof_addr = 0x794,
+ .csid_pxl_timestamp_perv0_sof_addr = 0x798,
+ .csid_pxl_timestamp_perv1_sof_addr = 0x79c,
+ .csid_pxl_timestamp_curr0_eof_addr = 0x7a0,
+ .csid_pxl_timestamp_curr1_eof_addr = 0x7a4,
+ .csid_pxl_timestamp_perv0_eof_addr = 0x7a8,
+ .csid_pxl_timestamp_perv1_eof_addr = 0x7ac,
+ /* configurations */
+ .pix_store_en_shift_val = 7,
+ .early_eof_en_shift_val = 29,
};
-static struct cam_ife_csid_rdi_reg_offset
- cam_ife_csid_lite_170_rdi_1_reg_offset = {
+static struct cam_ife_csid_rdi_reg_offset cam_ife_csid_175_rdi_0_reg_offset = {
.csid_rdi_irq_status_addr = 0x40,
.csid_rdi_irq_mask_addr = 0x44,
.csid_rdi_irq_clear_addr = 0x48,
@@ -100,9 +137,7 @@ static struct cam_ife_csid_rdi_reg_offset
.csid_rdi_byte_cntr_pong_addr = 0x3e4,
};
-static struct cam_ife_csid_rdi_reg_offset
- cam_ife_csid_lite_170_rdi_2_reg_offset = {
-
+static struct cam_ife_csid_rdi_reg_offset cam_ife_csid_175_rdi_1_reg_offset = {
.csid_rdi_irq_status_addr = 0x50,
.csid_rdi_irq_mask_addr = 0x54,
.csid_rdi_irq_clear_addr = 0x58,
@@ -120,7 +155,6 @@ static struct cam_ife_csid_rdi_reg_offset
.csid_rdi_rpp_pix_drop_period_addr = 0x428,
.csid_rdi_rpp_line_drop_pattern_addr = 0x42c,
.csid_rdi_rpp_line_drop_period_addr = 0x430,
- .csid_rdi_yuv_chroma_conversion_addr = 0x434,
.csid_rdi_rst_strobes_addr = 0x440,
.csid_rdi_status_addr = 0x450,
.csid_rdi_misr_val0_addr = 0x454,
@@ -144,9 +178,7 @@ static struct cam_ife_csid_rdi_reg_offset
.csid_rdi_byte_cntr_pong_addr = 0x4e4,
};
-static struct cam_ife_csid_rdi_reg_offset
- cam_ife_csid_lite_170_rdi_3_reg_offset = {
-
+static struct cam_ife_csid_rdi_reg_offset cam_ife_csid_175_rdi_2_reg_offset = {
.csid_rdi_irq_status_addr = 0x60,
.csid_rdi_irq_mask_addr = 0x64,
.csid_rdi_irq_clear_addr = 0x68,
@@ -189,8 +221,7 @@ static struct cam_ife_csid_rdi_reg_offset
};
static struct cam_ife_csid_csi2_rx_reg_offset
- cam_ife_csid_lite_170_csi2_reg_offset = {
-
+ cam_ife_csid_175_csi2_reg_offset = {
.csid_csi2_rx_irq_status_addr = 0x20,
.csid_csi2_rx_irq_mask_addr = 0x24,
.csid_csi2_rx_irq_clear_addr = 0x28,
@@ -232,12 +263,11 @@ static struct cam_ife_csid_csi2_rx_reg_offset
.csi2_capture_short_pkt_vc_shift = 15,
.csi2_capture_cphy_pkt_dt_shift = 20,
.csi2_capture_cphy_pkt_vc_shift = 26,
+ .csi2_rx_phy_num_mask = 0x3,
};
-
static struct cam_ife_csid_csi2_tpg_reg_offset
- cam_ife_csid_lite_170_tpg_reg_offset = {
-
+ cam_ife_csid_175_tpg_reg_offset = {
/*CSID TPG control */
.csid_tpg_ctrl_addr = 0x600,
.csid_tpg_vc_cfg0_addr = 0x604,
@@ -257,16 +287,14 @@ static struct cam_ife_csid_csi2_tpg_reg_offset
.csid_tpg_cgen_n_y1_addr = 0x664,
.csid_tpg_cgen_n_y2_addr = 0x668,
- /*configurations */
+ /* configurations */
.tpg_dtn_cfg_offset = 0xc,
.tpg_cgen_cfg_offset = 0x20,
.tpg_cpas_ife_reg_offset = 0x28,
};
-
static struct cam_ife_csid_common_reg_offset
- cam_csid_lite_170_cmn_reg_offset = {
-
+ cam_ife_csid_175_cmn_reg_offset = {
.csid_hw_version_addr = 0x0,
.csid_cfg0_addr = 0x4,
.csid_ctrl_addr = 0x8,
@@ -284,8 +312,10 @@ static struct cam_ife_csid_common_reg_offset
.major_version = 1,
.minor_version = 7,
.version_incr = 0,
- .no_rdis = 4,
- .no_pix = 0,
+ .num_rdis = 3,
+ .num_pix = 1,
+ .num_ppp = 1,
+ .csid_reg_rst_stb = 1,
.csid_rst_stb = 0x1e,
.csid_rst_stb_sw_all = 0x1f,
.path_rst_stb_all = 0x7f,
@@ -301,19 +331,23 @@ static struct cam_ife_csid_common_reg_offset
.crop_shift = 16,
.ipp_irq_mask_all = 0x7FFF,
.rdi_irq_mask_all = 0x7FFF,
+ .ppp_irq_mask_all = 0xFFFF,
+ .measure_en_hbi_vbi_cnt_mask = 0xC,
+ .format_measure_en_val = 1,
};
-struct cam_ife_csid_reg_offset cam_ife_csid_lite_170_reg_offset = {
- .cmn_reg = &cam_csid_lite_170_cmn_reg_offset,
- .csi2_reg = &cam_ife_csid_lite_170_csi2_reg_offset,
- .ipp_reg = NULL,
+static struct cam_ife_csid_reg_offset cam_ife_csid_175_reg_offset = {
+ .cmn_reg = &cam_ife_csid_175_cmn_reg_offset,
+ .csi2_reg = &cam_ife_csid_175_csi2_reg_offset,
+ .ipp_reg = &cam_ife_csid_175_ipp_reg_offset,
+ .ppp_reg = &cam_ife_csid_175_ppp_reg_offset,
.rdi_reg = {
- &cam_ife_csid_lite_170_rdi_0_reg_offset,
- &cam_ife_csid_lite_170_rdi_1_reg_offset,
- &cam_ife_csid_lite_170_rdi_2_reg_offset,
- &cam_ife_csid_lite_170_rdi_3_reg_offset,
+ &cam_ife_csid_175_rdi_0_reg_offset,
+ &cam_ife_csid_175_rdi_1_reg_offset,
+ &cam_ife_csid_175_rdi_2_reg_offset,
+ NULL,
},
- .tpg_reg = &cam_ife_csid_lite_170_tpg_reg_offset,
+ .tpg_reg = &cam_ife_csid_175_tpg_reg_offset,
};
-#endif /*_CAM_IFE_CSID_LITE170_H_ */
+#endif /*_CAM_IFE_CSID_175_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h
new file mode 100644
index 000000000000..8a78fe0b9b0d
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h
@@ -0,0 +1,369 @@
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CAM_IFE_CSID_175_200_H_
+#define _CAM_IFE_CSID_175_200_H_
+
+#include "cam_ife_csid_core.h"
+
+static struct cam_ife_csid_pxl_reg_offset
+ cam_ife_csid_175_200_ipp_reg_offset = {
+ .csid_pxl_irq_status_addr = 0x30,
+ .csid_pxl_irq_mask_addr = 0x34,
+ .csid_pxl_irq_clear_addr = 0x38,
+ .csid_pxl_irq_set_addr = 0x3c,
+
+ .csid_pxl_cfg0_addr = 0x200,
+ .csid_pxl_cfg1_addr = 0x204,
+ .csid_pxl_ctrl_addr = 0x208,
+ .csid_pxl_frm_drop_pattern_addr = 0x20c,
+ .csid_pxl_frm_drop_period_addr = 0x210,
+ .csid_pxl_irq_subsample_pattern_addr = 0x214,
+ .csid_pxl_irq_subsample_period_addr = 0x218,
+ .csid_pxl_hcrop_addr = 0x21c,
+ .csid_pxl_vcrop_addr = 0x220,
+ .csid_pxl_pix_drop_pattern_addr = 0x224,
+ .csid_pxl_pix_drop_period_addr = 0x228,
+ .csid_pxl_line_drop_pattern_addr = 0x22c,
+ .csid_pxl_line_drop_period_addr = 0x230,
+ .csid_pxl_rst_strobes_addr = 0x240,
+ .csid_pxl_status_addr = 0x254,
+ .csid_pxl_misr_val_addr = 0x258,
+ .csid_pxl_format_measure_cfg0_addr = 0x270,
+ .csid_pxl_format_measure_cfg1_addr = 0x274,
+ .csid_pxl_format_measure0_addr = 0x278,
+ .csid_pxl_format_measure1_addr = 0x27c,
+ .csid_pxl_format_measure2_addr = 0x280,
+ .csid_pxl_timestamp_curr0_sof_addr = 0x290,
+ .csid_pxl_timestamp_curr1_sof_addr = 0x294,
+ .csid_pxl_timestamp_perv0_sof_addr = 0x298,
+ .csid_pxl_timestamp_perv1_sof_addr = 0x29c,
+ .csid_pxl_timestamp_curr0_eof_addr = 0x2a0,
+ .csid_pxl_timestamp_curr1_eof_addr = 0x2a4,
+ .csid_pxl_timestamp_perv0_eof_addr = 0x2a8,
+ .csid_pxl_timestamp_perv1_eof_addr = 0x2ac,
+ /* configurations */
+ .pix_store_en_shift_val = 7,
+ .early_eof_en_shift_val = 29,
+ .ccif_violation_en = 1,
+};
+
+static struct cam_ife_csid_pxl_reg_offset
+ cam_ife_csid_175_200_ppp_reg_offset = {
+ .csid_pxl_irq_status_addr = 0xa0,
+ .csid_pxl_irq_mask_addr = 0xa4,
+ .csid_pxl_irq_clear_addr = 0xa8,
+ .csid_pxl_irq_set_addr = 0xac,
+
+ .csid_pxl_cfg0_addr = 0x700,
+ .csid_pxl_cfg1_addr = 0x704,
+ .csid_pxl_ctrl_addr = 0x708,
+ .csid_pxl_frm_drop_pattern_addr = 0x70c,
+ .csid_pxl_frm_drop_period_addr = 0x710,
+ .csid_pxl_irq_subsample_pattern_addr = 0x714,
+ .csid_pxl_irq_subsample_period_addr = 0x718,
+ .csid_pxl_hcrop_addr = 0x71c,
+ .csid_pxl_vcrop_addr = 0x720,
+ .csid_pxl_pix_drop_pattern_addr = 0x724,
+ .csid_pxl_pix_drop_period_addr = 0x728,
+ .csid_pxl_line_drop_pattern_addr = 0x72c,
+ .csid_pxl_line_drop_period_addr = 0x730,
+ .csid_pxl_rst_strobes_addr = 0x740,
+ .csid_pxl_status_addr = 0x754,
+ .csid_pxl_misr_val_addr = 0x758,
+ .csid_pxl_format_measure_cfg0_addr = 0x770,
+ .csid_pxl_format_measure_cfg1_addr = 0x774,
+ .csid_pxl_format_measure0_addr = 0x778,
+ .csid_pxl_format_measure1_addr = 0x77c,
+ .csid_pxl_format_measure2_addr = 0x780,
+ .csid_pxl_timestamp_curr0_sof_addr = 0x790,
+ .csid_pxl_timestamp_curr1_sof_addr = 0x794,
+ .csid_pxl_timestamp_perv0_sof_addr = 0x798,
+ .csid_pxl_timestamp_perv1_sof_addr = 0x79c,
+ .csid_pxl_timestamp_curr0_eof_addr = 0x7a0,
+ .csid_pxl_timestamp_curr1_eof_addr = 0x7a4,
+ .csid_pxl_timestamp_perv0_eof_addr = 0x7a8,
+ .csid_pxl_timestamp_perv1_eof_addr = 0x7ac,
+ /* configurations */
+ .pix_store_en_shift_val = 7,
+ .early_eof_en_shift_val = 29,
+ .ccif_violation_en = 1,
+};
+
+
+static struct cam_ife_csid_rdi_reg_offset
+ cam_ife_csid_175_200_rdi_0_reg_offset = {
+ .csid_rdi_irq_status_addr = 0x40,
+ .csid_rdi_irq_mask_addr = 0x44,
+ .csid_rdi_irq_clear_addr = 0x48,
+ .csid_rdi_irq_set_addr = 0x4c,
+ .csid_rdi_cfg0_addr = 0x300,
+ .csid_rdi_cfg1_addr = 0x304,
+ .csid_rdi_ctrl_addr = 0x308,
+ .csid_rdi_frm_drop_pattern_addr = 0x30c,
+ .csid_rdi_frm_drop_period_addr = 0x310,
+ .csid_rdi_irq_subsample_pattern_addr = 0x314,
+ .csid_rdi_irq_subsample_period_addr = 0x318,
+ .csid_rdi_rpp_hcrop_addr = 0x31c,
+ .csid_rdi_rpp_vcrop_addr = 0x320,
+ .csid_rdi_rpp_pix_drop_pattern_addr = 0x324,
+ .csid_rdi_rpp_pix_drop_period_addr = 0x328,
+ .csid_rdi_rpp_line_drop_pattern_addr = 0x32c,
+ .csid_rdi_rpp_line_drop_period_addr = 0x330,
+ .csid_rdi_rst_strobes_addr = 0x340,
+ .csid_rdi_status_addr = 0x350,
+ .csid_rdi_misr_val0_addr = 0x354,
+ .csid_rdi_misr_val1_addr = 0x358,
+ .csid_rdi_misr_val2_addr = 0x35c,
+ .csid_rdi_misr_val3_addr = 0x360,
+ .csid_rdi_format_measure_cfg0_addr = 0x370,
+ .csid_rdi_format_measure_cfg1_addr = 0x374,
+ .csid_rdi_format_measure0_addr = 0x378,
+ .csid_rdi_format_measure1_addr = 0x37c,
+ .csid_rdi_format_measure2_addr = 0x380,
+ .csid_rdi_timestamp_curr0_sof_addr = 0x390,
+ .csid_rdi_timestamp_curr1_sof_addr = 0x394,
+ .csid_rdi_timestamp_prev0_sof_addr = 0x398,
+ .csid_rdi_timestamp_prev1_sof_addr = 0x39c,
+ .csid_rdi_timestamp_curr0_eof_addr = 0x3a0,
+ .csid_rdi_timestamp_curr1_eof_addr = 0x3a4,
+ .csid_rdi_timestamp_prev0_eof_addr = 0x3a8,
+ .csid_rdi_timestamp_prev1_eof_addr = 0x3ac,
+ .csid_rdi_byte_cntr_ping_addr = 0x3e0,
+ .csid_rdi_byte_cntr_pong_addr = 0x3e4,
+ .ccif_violation_en = 1,
+};
+
+static struct cam_ife_csid_rdi_reg_offset
+ cam_ife_csid_175_200_rdi_1_reg_offset = {
+ .csid_rdi_irq_status_addr = 0x50,
+ .csid_rdi_irq_mask_addr = 0x54,
+ .csid_rdi_irq_clear_addr = 0x58,
+ .csid_rdi_irq_set_addr = 0x5c,
+ .csid_rdi_cfg0_addr = 0x400,
+ .csid_rdi_cfg1_addr = 0x404,
+ .csid_rdi_ctrl_addr = 0x408,
+ .csid_rdi_frm_drop_pattern_addr = 0x40c,
+ .csid_rdi_frm_drop_period_addr = 0x410,
+ .csid_rdi_irq_subsample_pattern_addr = 0x414,
+ .csid_rdi_irq_subsample_period_addr = 0x418,
+ .csid_rdi_rpp_hcrop_addr = 0x41c,
+ .csid_rdi_rpp_vcrop_addr = 0x420,
+ .csid_rdi_rpp_pix_drop_pattern_addr = 0x424,
+ .csid_rdi_rpp_pix_drop_period_addr = 0x428,
+ .csid_rdi_rpp_line_drop_pattern_addr = 0x42c,
+ .csid_rdi_rpp_line_drop_period_addr = 0x430,
+ .csid_rdi_rst_strobes_addr = 0x440,
+ .csid_rdi_status_addr = 0x450,
+ .csid_rdi_misr_val0_addr = 0x454,
+ .csid_rdi_misr_val1_addr = 0x458,
+ .csid_rdi_misr_val2_addr = 0x45c,
+ .csid_rdi_misr_val3_addr = 0x460,
+ .csid_rdi_format_measure_cfg0_addr = 0x470,
+ .csid_rdi_format_measure_cfg1_addr = 0x474,
+ .csid_rdi_format_measure0_addr = 0x478,
+ .csid_rdi_format_measure1_addr = 0x47c,
+ .csid_rdi_format_measure2_addr = 0x480,
+ .csid_rdi_timestamp_curr0_sof_addr = 0x490,
+ .csid_rdi_timestamp_curr1_sof_addr = 0x494,
+ .csid_rdi_timestamp_prev0_sof_addr = 0x498,
+ .csid_rdi_timestamp_prev1_sof_addr = 0x49c,
+ .csid_rdi_timestamp_curr0_eof_addr = 0x4a0,
+ .csid_rdi_timestamp_curr1_eof_addr = 0x4a4,
+ .csid_rdi_timestamp_prev0_eof_addr = 0x4a8,
+ .csid_rdi_timestamp_prev1_eof_addr = 0x4ac,
+ .csid_rdi_byte_cntr_ping_addr = 0x4e0,
+ .csid_rdi_byte_cntr_pong_addr = 0x4e4,
+ .ccif_violation_en = 1,
+};
+
+static struct cam_ife_csid_rdi_reg_offset
+ cam_ife_csid_175_200_rdi_2_reg_offset = {
+ .csid_rdi_irq_status_addr = 0x60,
+ .csid_rdi_irq_mask_addr = 0x64,
+ .csid_rdi_irq_clear_addr = 0x68,
+ .csid_rdi_irq_set_addr = 0x6c,
+ .csid_rdi_cfg0_addr = 0x500,
+ .csid_rdi_cfg1_addr = 0x504,
+ .csid_rdi_ctrl_addr = 0x508,
+ .csid_rdi_frm_drop_pattern_addr = 0x50c,
+ .csid_rdi_frm_drop_period_addr = 0x510,
+ .csid_rdi_irq_subsample_pattern_addr = 0x514,
+ .csid_rdi_irq_subsample_period_addr = 0x518,
+ .csid_rdi_rpp_hcrop_addr = 0x51c,
+ .csid_rdi_rpp_vcrop_addr = 0x520,
+ .csid_rdi_rpp_pix_drop_pattern_addr = 0x524,
+ .csid_rdi_rpp_pix_drop_period_addr = 0x528,
+ .csid_rdi_rpp_line_drop_pattern_addr = 0x52c,
+ .csid_rdi_rpp_line_drop_period_addr = 0x530,
+ .csid_rdi_yuv_chroma_conversion_addr = 0x534,
+ .csid_rdi_rst_strobes_addr = 0x540,
+ .csid_rdi_status_addr = 0x550,
+ .csid_rdi_misr_val0_addr = 0x554,
+ .csid_rdi_misr_val1_addr = 0x558,
+ .csid_rdi_misr_val2_addr = 0x55c,
+ .csid_rdi_misr_val3_addr = 0x560,
+ .csid_rdi_format_measure_cfg0_addr = 0x570,
+ .csid_rdi_format_measure_cfg1_addr = 0x574,
+ .csid_rdi_format_measure0_addr = 0x578,
+ .csid_rdi_format_measure1_addr = 0x57c,
+ .csid_rdi_format_measure2_addr = 0x580,
+ .csid_rdi_timestamp_curr0_sof_addr = 0x590,
+ .csid_rdi_timestamp_curr1_sof_addr = 0x594,
+ .csid_rdi_timestamp_prev0_sof_addr = 0x598,
+ .csid_rdi_timestamp_prev1_sof_addr = 0x59c,
+ .csid_rdi_timestamp_curr0_eof_addr = 0x5a0,
+ .csid_rdi_timestamp_curr1_eof_addr = 0x5a4,
+ .csid_rdi_timestamp_prev0_eof_addr = 0x5a8,
+ .csid_rdi_timestamp_prev1_eof_addr = 0x5ac,
+ .csid_rdi_byte_cntr_ping_addr = 0x5e0,
+ .csid_rdi_byte_cntr_pong_addr = 0x5e4,
+ .ccif_violation_en = 1,
+};
+
+static struct cam_ife_csid_csi2_rx_reg_offset
+ cam_ife_csid_175_200_csi2_reg_offset = {
+ .csid_csi2_rx_irq_status_addr = 0x20,
+ .csid_csi2_rx_irq_mask_addr = 0x24,
+ .csid_csi2_rx_irq_clear_addr = 0x28,
+ .csid_csi2_rx_irq_set_addr = 0x2c,
+
+ /*CSI2 rx control */
+ .csid_csi2_rx_cfg0_addr = 0x100,
+ .csid_csi2_rx_cfg1_addr = 0x104,
+ .csid_csi2_rx_capture_ctrl_addr = 0x108,
+ .csid_csi2_rx_rst_strobes_addr = 0x110,
+ .csid_csi2_rx_cap_unmap_long_pkt_hdr_0_addr = 0x120,
+ .csid_csi2_rx_cap_unmap_long_pkt_hdr_1_addr = 0x124,
+ .csid_csi2_rx_captured_short_pkt_0_addr = 0x128,
+ .csid_csi2_rx_captured_short_pkt_1_addr = 0x12c,
+ .csid_csi2_rx_captured_long_pkt_0_addr = 0x130,
+ .csid_csi2_rx_captured_long_pkt_1_addr = 0x134,
+ .csid_csi2_rx_captured_long_pkt_ftr_addr = 0x138,
+ .csid_csi2_rx_captured_cphy_pkt_hdr_addr = 0x13c,
+ .csid_csi2_rx_lane0_misr_addr = 0x150,
+ .csid_csi2_rx_lane1_misr_addr = 0x154,
+ .csid_csi2_rx_lane2_misr_addr = 0x158,
+ .csid_csi2_rx_lane3_misr_addr = 0x15c,
+ .csid_csi2_rx_total_pkts_rcvd_addr = 0x160,
+ .csid_csi2_rx_stats_ecc_addr = 0x164,
+ .csid_csi2_rx_total_crc_err_addr = 0x168,
+ .csid_csi2_rx_de_scramble_type3_cfg0_addr = 0x170,
+ .csid_csi2_rx_de_scramble_type3_cfg1_addr = 0x174,
+ .csid_csi2_rx_de_scramble_type2_cfg0_addr = 0x178,
+ .csid_csi2_rx_de_scramble_type2_cfg1_addr = 0x17c,
+ .csid_csi2_rx_de_scramble_type1_cfg0_addr = 0x180,
+ .csid_csi2_rx_de_scramble_type1_cfg1_addr = 0x184,
+ .csid_csi2_rx_de_scramble_type0_cfg0_addr = 0x188,
+ .csid_csi2_rx_de_scramble_type0_cfg1_addr = 0x18c,
+
+ .csi2_rst_srb_all = 0x3FFF,
+ .csi2_rst_done_shift_val = 27,
+ .csi2_irq_mask_all = 0xFFFFFFF,
+ .csi2_misr_enable_shift_val = 6,
+ .csi2_vc_mode_shift_val = 2,
+ .csi2_capture_long_pkt_en_shift = 0,
+ .csi2_capture_short_pkt_en_shift = 1,
+ .csi2_capture_cphy_pkt_en_shift = 2,
+ .csi2_capture_long_pkt_dt_shift = 4,
+ .csi2_capture_long_pkt_vc_shift = 10,
+ .csi2_capture_short_pkt_vc_shift = 15,
+ .csi2_capture_cphy_pkt_dt_shift = 20,
+ .csi2_capture_cphy_pkt_vc_shift = 26,
+ .csi2_rx_phy_num_mask = 0x7,
+};
+
+static struct cam_ife_csid_csi2_tpg_reg_offset
+ cam_ife_csid_175_200_tpg_reg_offset = {
+ /*CSID TPG control */
+ .csid_tpg_ctrl_addr = 0x600,
+ .csid_tpg_vc_cfg0_addr = 0x604,
+ .csid_tpg_vc_cfg1_addr = 0x608,
+ .csid_tpg_lfsr_seed_addr = 0x60c,
+ .csid_tpg_dt_n_cfg_0_addr = 0x610,
+ .csid_tpg_dt_n_cfg_1_addr = 0x614,
+ .csid_tpg_dt_n_cfg_2_addr = 0x618,
+ .csid_tpg_color_bars_cfg_addr = 0x640,
+ .csid_tpg_color_box_cfg_addr = 0x644,
+ .csid_tpg_common_gen_cfg_addr = 0x648,
+ .csid_tpg_cgen_n_cfg_addr = 0x650,
+ .csid_tpg_cgen_n_x0_addr = 0x654,
+ .csid_tpg_cgen_n_x1_addr = 0x658,
+ .csid_tpg_cgen_n_x2_addr = 0x65c,
+ .csid_tpg_cgen_n_xy_addr = 0x660,
+ .csid_tpg_cgen_n_y1_addr = 0x664,
+ .csid_tpg_cgen_n_y2_addr = 0x668,
+
+ /* configurations */
+ .tpg_dtn_cfg_offset = 0xc,
+ .tpg_cgen_cfg_offset = 0x20,
+ .tpg_cpas_ife_reg_offset = 0x28,
+};
+
+static struct cam_ife_csid_common_reg_offset
+ cam_ife_csid_175_200_cmn_reg_offset = {
+ .csid_hw_version_addr = 0x0,
+ .csid_cfg0_addr = 0x4,
+ .csid_ctrl_addr = 0x8,
+ .csid_reset_addr = 0xc,
+ .csid_rst_strobes_addr = 0x10,
+
+ .csid_test_bus_ctrl_addr = 0x14,
+ .csid_top_irq_status_addr = 0x70,
+ .csid_top_irq_mask_addr = 0x74,
+ .csid_top_irq_clear_addr = 0x78,
+ .csid_top_irq_set_addr = 0x7c,
+ .csid_irq_cmd_addr = 0x80,
+
+ /*configurations */
+ .major_version = 1,
+ .minor_version = 7,
+ .version_incr = 5,
+ .num_rdis = 3,
+ .num_pix = 1,
+ .num_ppp = 1,
+ .csid_reg_rst_stb = 1,
+ .csid_rst_stb = 0x1e,
+ .csid_rst_stb_sw_all = 0x1f,
+ .path_rst_stb_all = 0x7f,
+ .path_rst_done_shift_val = 1,
+ .path_en_shift_val = 31,
+ .dt_id_shift_val = 27,
+ .vc_shift_val = 22,
+ .dt_shift_val = 16,
+ .fmt_shift_val = 12,
+ .plain_fmt_shit_val = 10,
+ .crop_v_en_shift_val = 6,
+ .crop_h_en_shift_val = 5,
+ .crop_shift = 16,
+ .ipp_irq_mask_all = 0xFFFF,
+ .rdi_irq_mask_all = 0xFFFF,
+ .ppp_irq_mask_all = 0xFFFF,
+ .measure_en_hbi_vbi_cnt_mask = 0xC,
+ .format_measure_en_val = 1,
+};
+
+static struct cam_ife_csid_reg_offset cam_ife_csid_175_200_reg_offset = {
+ .cmn_reg = &cam_ife_csid_175_200_cmn_reg_offset,
+ .csi2_reg = &cam_ife_csid_175_200_csi2_reg_offset,
+ .ipp_reg = &cam_ife_csid_175_200_ipp_reg_offset,
+ .ppp_reg = &cam_ife_csid_175_200_ppp_reg_offset,
+ .rdi_reg = {
+ &cam_ife_csid_175_200_rdi_0_reg_offset,
+ &cam_ife_csid_175_200_rdi_1_reg_offset,
+ &cam_ife_csid_175_200_rdi_2_reg_offset,
+ NULL,
+ },
+ .tpg_reg = &cam_ife_csid_175_200_tpg_reg_offset,
+};
+
+#endif /*_CAM_IFE_CSID_175_200_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c
index f894daa846b9..80701bf6f8d0 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -14,21 +14,42 @@
#include <linux/module.h>
#include "cam_ife_csid_core.h"
#include "cam_ife_csid170.h"
+#include "cam_ife_csid175.h"
+#include "cam_ife_csid175_200.h"
#include "cam_ife_csid_dev.h"
#define CAM_CSID_DRV_NAME "csid_17x"
#define CAM_CSID_VERSION_V170 0x10070000
+#define CAM_CSID_VERSION_V175 0x10070050
static struct cam_ife_csid_hw_info cam_ife_csid170_hw_info = {
.csid_reg = &cam_ife_csid_170_reg_offset,
.hw_dts_version = CAM_CSID_VERSION_V170,
};
+static struct cam_ife_csid_hw_info cam_ife_csid175_hw_info = {
+ .csid_reg = &cam_ife_csid_175_reg_offset,
+ .hw_dts_version = CAM_CSID_VERSION_V175,
+};
+
+static struct cam_ife_csid_hw_info cam_ife_csid175_200_hw_info = {
+ .csid_reg = &cam_ife_csid_175_200_reg_offset,
+ .hw_dts_version = CAM_CSID_VERSION_V175,
+};
+
static const struct of_device_id cam_ife_csid17x_dt_match[] = {
{
.compatible = "qcom,csid170",
.data = &cam_ife_csid170_hw_info,
},
+ {
+ .compatible = "qcom,csid175",
+ .data = &cam_ife_csid175_hw_info,
+ },
+ {
+ .compatible = "qcom,csid175_200",
+ .data = &cam_ife_csid175_200_hw_info,
+ },
{}
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
index f3a15558bb1b..779d04460e2c 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, 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
@@ -67,6 +67,7 @@ static int cam_ife_csid_is_ipp_ppp_format_supported(
case CAM_FORMAT_DPCM_12_8_12:
case CAM_FORMAT_DPCM_14_8_14:
case CAM_FORMAT_DPCM_14_10_14:
+ case CAM_FORMAT_DPCM_12_10_12:
rc = 0;
break;
default:
@@ -206,6 +207,10 @@ static int cam_ife_csid_get_format_rdi(
*decode_fmt = 0xC;
*plain_fmt = 0x1;
break;
+ case CAM_FORMAT_DPCM_12_10_12:
+ *decode_fmt = 0xD;
+ *plain_fmt = 0x1;
+ break;
default:
rc = -EINVAL;
break;
@@ -280,6 +285,10 @@ static int cam_ife_csid_get_format_ipp_ppp(
*decode_fmt = 0xC;
*plain_fmt = 0x1;
break;
+ case CAM_FORMAT_DPCM_12_10_12:
+ *decode_fmt = 0xD;
+ *plain_fmt = 0x1;
+ break;
default:
CAM_ERR(CAM_ISP, "Unsupported format %d",
in_format);
@@ -309,6 +318,9 @@ static int cam_ife_csid_cid_get(struct cam_ife_csid_hw *csid_hw,
if (cid_data->vc == vc && cid_data->dt == dt) {
cid_data->cnt++;
*res = &csid_hw->cid_res[i];
+ CAM_DBG(CAM_ISP, "CSID:%d CID %d allocated",
+ csid_hw->hw_intf->hw_idx,
+ csid_hw->cid_res[i].res_id);
return 0;
}
}
@@ -418,8 +430,23 @@ static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw)
cam_io_w_mb(0x2, soc_info->reg_map[0].mem_base +
csid_reg->rdi_reg[i]->csid_rdi_cfg0_addr);
- /* perform the top CSID HW and SW registers reset */
- cam_io_w_mb(csid_reg->cmn_reg->csid_rst_stb_sw_all,
+ /* perform the top CSID HW registers reset */
+ cam_io_w_mb(csid_reg->cmn_reg->csid_rst_stb,
+ soc_info->reg_map[0].mem_base +
+ csid_reg->cmn_reg->csid_rst_strobes_addr);
+
+ rc = readl_poll_timeout(soc_info->reg_map[0].mem_base +
+ csid_reg->cmn_reg->csid_top_irq_status_addr,
+ status, (status & 0x1) == 0x1,
+ CAM_IFE_CSID_TIMEOUT_SLEEP_US, CAM_IFE_CSID_TIMEOUT_ALL_US);
+ if (rc < 0) {
+ CAM_ERR(CAM_ISP, "CSID:%d csid_reset fail rc = %d",
+ csid_hw->hw_intf->hw_idx, rc);
+ rc = -ETIMEDOUT;
+ }
+
+ /* perform the SW registers reset */
+ cam_io_w_mb(csid_reg->cmn_reg->csid_reg_rst_stb,
soc_info->reg_map[0].mem_base +
csid_reg->cmn_reg->csid_rst_strobes_addr);
@@ -433,6 +460,7 @@ static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw)
rc = -ETIMEDOUT;
}
+ usleep_range(3000, 3010);
val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr);
if (val != 0)
@@ -647,12 +675,12 @@ static int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw,
CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc);
goto end;
}
- CAM_DBG(CAM_ISP, "HW version: %d", camera_hw_version);
+ CAM_DBG(CAM_ISP, "HW version: %x", camera_hw_version);
switch (camera_hw_version) {
case CAM_CPAS_TITAN_NONE:
case CAM_CPAS_TITAN_MAX:
- CAM_ERR(CAM_ISP, "Invalid HW version: %d", camera_hw_version);
+ CAM_ERR(CAM_ISP, "Invalid HW version: %x", camera_hw_version);
break;
case CAM_CPAS_TITAN_170_V100:
case CAM_CPAS_TITAN_170_V110:
@@ -1093,6 +1121,7 @@ static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw)
int rc = -EINVAL;
struct cam_hw_soc_info *soc_info;
const struct cam_ife_csid_reg_offset *csid_reg;
+ unsigned long flags;
/* Check for refcount */
if (!csid_hw->hw_info->open_count) {
@@ -1127,6 +1156,9 @@ static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw)
CAM_ERR(CAM_ISP, "CSID:%d Disable CSID SOC failed",
csid_hw->hw_intf->hw_idx);
+ spin_lock_irqsave(&csid_hw->lock_state, flags);
+ csid_hw->device_enabled = 0;
+ spin_unlock_irqrestore(&csid_hw->lock_state, flags);
csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
csid_hw->error_irq_count = 0;
@@ -1327,10 +1359,12 @@ static int cam_ife_csid_enable_csi2(
return rc;
/* rx cfg0 */
+ val = 0;
val = (csid_hw->csi2_rx_cfg.lane_num - 1) |
(csid_hw->csi2_rx_cfg.lane_cfg << 4) |
(csid_hw->csi2_rx_cfg.lane_type << 24);
- val |= (csid_hw->csi2_rx_cfg.phy_sel & 0x3) << 20;
+ val |= (csid_hw->csi2_rx_cfg.phy_sel &
+ csid_reg->csi2_reg->csi2_rx_phy_num_mask) << 20;
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->csi2_reg->csid_csi2_rx_cfg0_addr);
@@ -1753,6 +1787,9 @@ static int cam_ife_csid_enable_pxl_path(
/* Enable the required pxl path interrupts */
val = CSID_PATH_INFO_RST_DONE | CSID_PATH_ERROR_FIFO_OVERFLOW;
+ if (pxl_reg->ccif_violation_en)
+ val |= CSID_PATH_ERROR_CCIF_VIOLATION;
+
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)
val |= CSID_PATH_INFO_INPUT_SOF;
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)
@@ -1775,6 +1812,7 @@ static int cam_ife_csid_disable_pxl_path(
enum cam_ife_csid_halt_cmd stop_cmd)
{
int rc = 0;
+ uint32_t val = 0;
const struct cam_ife_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info;
struct cam_ife_csid_path_cfg *path_data;
@@ -1835,6 +1873,17 @@ static int cam_ife_csid_disable_pxl_path(
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
pxl_reg->csid_pxl_irq_mask_addr);
+ if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER ||
+ path_data->sync_mode == CAM_ISP_HW_SYNC_NONE) {
+ /* configure Halt */
+ val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ pxl_reg->csid_pxl_ctrl_addr);
+ val &= ~0x3;
+ val |= stop_cmd;
+ cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+ pxl_reg->csid_pxl_ctrl_addr);
+ }
+
return rc;
}
@@ -2063,6 +2112,9 @@ static int cam_ife_csid_enable_rdi_path(
/* Enable the required RDI interrupts */
val = CSID_PATH_INFO_RST_DONE | CSID_PATH_ERROR_FIFO_OVERFLOW;
+ if (csid_reg->rdi_reg[id]->ccif_violation_en)
+ val |= CSID_PATH_ERROR_CCIF_VIOLATION;
+
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)
val |= CSID_PATH_INFO_INPUT_SOF;
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)
@@ -2083,7 +2135,7 @@ static int cam_ife_csid_disable_rdi_path(
enum cam_ife_csid_halt_cmd stop_cmd)
{
int rc = 0;
- uint32_t id;
+ uint32_t id, val = 0;
const struct cam_ife_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info;
@@ -2128,6 +2180,62 @@ static int cam_ife_csid_disable_rdi_path(
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr);
+ /* Halt the RDI path */
+ val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr);
+ val &= ~0x3;
+ val |= stop_cmd;
+ cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+ csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr);
+
+ return rc;
+}
+
+static int cam_ife_csid_poll_stop_status(
+ struct cam_ife_csid_hw *csid_hw,
+ uint32_t res_mask)
+{
+ int rc = 0;
+ uint32_t csid_status_addr = 0, val = 0, res_id = 0;
+ const struct cam_ife_csid_reg_offset *csid_reg;
+ struct cam_hw_soc_info *soc_info;
+
+ csid_reg = csid_hw->csid_info->csid_reg;
+ soc_info = &csid_hw->hw_info->soc_info;
+
+ for (; res_id < CAM_IFE_PIX_PATH_RES_MAX; res_id++, res_mask >>= 1) {
+ if ((res_mask & 0x1) == 0)
+ continue;
+ val = 0;
+
+ if (res_id == CAM_IFE_PIX_PATH_RES_IPP) {
+ csid_status_addr =
+ csid_reg->ipp_reg->csid_pxl_status_addr;
+ } else if (res_id == CAM_IFE_PIX_PATH_RES_PPP) {
+ csid_status_addr =
+ csid_reg->ppp_reg->csid_pxl_status_addr;
+ } else {
+ csid_status_addr =
+ csid_reg->rdi_reg[res_id]->csid_rdi_status_addr;
+ }
+
+ CAM_DBG(CAM_ISP, "start polling CSID:%d res_id:%d",
+ csid_hw->hw_intf->hw_idx, res_id);
+
+ rc = readl_poll_timeout(soc_info->reg_map[0].mem_base +
+ csid_status_addr, val, (val & 0x1) == 0x1,
+ CAM_IFE_CSID_TIMEOUT_SLEEP_US,
+ CAM_IFE_CSID_TIMEOUT_ALL_US);
+ if (rc < 0) {
+ CAM_ERR(CAM_ISP, "CSID:%d res:%d halt failed rc %d",
+ csid_hw->hw_intf->hw_idx, res_id, rc);
+ rc = -ETIMEDOUT;
+ break;
+ }
+ CAM_DBG(CAM_ISP, "End polling CSID:%d res_id:%d",
+ csid_hw->hw_intf->hw_idx, res_id);
+ }
+
return rc;
}
@@ -2176,10 +2284,10 @@ static int cam_ife_csid_get_hbi_vbi(
rdi_reg->csid_rdi_format_measure2_addr);
}
- CAM_INFO_RATE_LIMIT(CAM_ISP, "Resource %u HBI: 0x%x", res->res_id,
- hbi);
- CAM_INFO_RATE_LIMIT(CAM_ISP, "Resource %u VBI: 0x%x", res->res_id,
- vbi);
+ CAM_INFO_RATE_LIMIT(CAM_ISP,
+ "Device %s index %u Resource %u HBI: 0x%x VBI: 0x%x",
+ soc_info->dev_name, soc_info->index,
+ res->res_id, hbi, vbi);
return 0;
}
@@ -2506,6 +2614,7 @@ static int cam_ife_csid_init_hw(void *hw_priv,
struct cam_hw_info *csid_hw_info;
struct cam_isp_resource_node *res;
const struct cam_ife_csid_reg_offset *csid_reg;
+ unsigned long flags;
if (!hw_priv || !init_args ||
(arg_size != sizeof(struct cam_isp_resource_node))) {
@@ -2573,6 +2682,10 @@ static int cam_ife_csid_init_hw(void *hw_priv,
if (rc)
cam_ife_csid_disable_hw(csid_hw);
+
+ spin_lock_irqsave(&csid_hw->lock_state, flags);
+ csid_hw->device_enabled = 1;
+ spin_unlock_irqrestore(&csid_hw->lock_state, flags);
end:
mutex_unlock(&csid_hw->hw_info->hw_mutex);
return rc;
@@ -2705,6 +2818,7 @@ static int cam_ife_csid_stop(void *hw_priv,
struct cam_isp_resource_node *res;
struct cam_csid_hw_stop_args *csid_stop;
uint32_t i;
+ uint32_t res_mask = 0;
if (!hw_priv || !stop_args ||
(arg_size != sizeof(struct cam_csid_hw_stop_args))) {
@@ -2736,6 +2850,7 @@ static int cam_ife_csid_stop(void *hw_priv,
rc = cam_ife_csid_tpg_stop(csid_hw, res);
break;
case CAM_ISP_RESOURCE_PIX_PATH:
+ res_mask |= (1 << res->res_id);
if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP ||
res->res_id == CAM_IFE_PIX_PATH_RES_PPP)
rc = cam_ife_csid_disable_pxl_path(csid_hw,
@@ -2753,6 +2868,9 @@ static int cam_ife_csid_stop(void *hw_priv,
}
}
+ if (res_mask)
+ rc = cam_ife_csid_poll_stop_status(csid_hw, res_mask);
+
for (i = 0; i < csid_stop->num_res; i++) {
res = csid_stop->node_res[i];
res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW;
@@ -2920,6 +3038,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
uint32_t val, irq_status_ppp = 0;
bool fatal_err_detected = false;
uint32_t sof_irq_debug_en = 0;
+ unsigned long flags;
csid_hw = (struct cam_ife_csid_hw *)data;
@@ -2985,65 +3104,74 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
complete(&csid_hw->csid_csi2_complete);
}
- if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 0 over flow",
- csid_hw->hw_intf->hw_idx);
- fatal_err_detected = true;
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 1 over flow",
- csid_hw->hw_intf->hw_idx);
- fatal_err_detected = true;
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 2 over flow",
- csid_hw->hw_intf->hw_idx);
- fatal_err_detected = true;
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 3 over flow",
- csid_hw->hw_intf->hw_idx);
- fatal_err_detected = true;
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d TG OVER FLOW",
- csid_hw->hw_intf->hw_idx);
- fatal_err_detected = true;
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_EOT_RECEPTION",
- csid_hw->hw_intf->hw_idx);
- csid_hw->error_irq_count++;
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_SOT_RECEPTION",
- csid_hw->hw_intf->hw_idx);
- csid_hw->error_irq_count++;
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_PH_CRC) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_PH_CRC",
- csid_hw->hw_intf->hw_idx);
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_CRC) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_CRC",
- csid_hw->hw_intf->hw_idx);
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_ECC) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_ECC",
- csid_hw->hw_intf->hw_idx);
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_MMAPPED_VC_DT) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d MMAPPED_VC_DT",
- csid_hw->hw_intf->hw_idx);
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_STREAM_UNDERFLOW",
- csid_hw->hw_intf->hw_idx);
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d UNBOUNDED_FRAME",
- csid_hw->hw_intf->hw_idx);
+ spin_lock_irqsave(&csid_hw->lock_state, flags);
+ if (csid_hw->device_enabled == 1) {
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 0 over flow",
+ csid_hw->hw_intf->hw_idx);
+ fatal_err_detected = true;
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 1 over flow",
+ csid_hw->hw_intf->hw_idx);
+ fatal_err_detected = true;
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 2 over flow",
+ csid_hw->hw_intf->hw_idx);
+ fatal_err_detected = true;
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 3 over flow",
+ csid_hw->hw_intf->hw_idx);
+ fatal_err_detected = true;
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d TG OVER FLOW",
+ csid_hw->hw_intf->hw_idx);
+ fatal_err_detected = true;
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP,
+ "CSID:%d CPHY_EOT_RECEPTION",
+ csid_hw->hw_intf->hw_idx);
+ csid_hw->error_irq_count++;
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP,
+ "CSID:%d CPHY_SOT_RECEPTION",
+ csid_hw->hw_intf->hw_idx);
+ csid_hw->error_irq_count++;
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_PH_CRC) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_PH_CRC",
+ csid_hw->hw_intf->hw_idx);
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_CRC) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_CRC",
+ csid_hw->hw_intf->hw_idx);
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_ECC) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_ECC",
+ csid_hw->hw_intf->hw_idx);
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_MMAPPED_VC_DT) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d MMAPPED_VC_DT",
+ csid_hw->hw_intf->hw_idx);
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP,
+ "CSID:%d ERROR_STREAM_UNDERFLOW",
+ csid_hw->hw_intf->hw_idx);
+ csid_hw->error_irq_count++;
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d UNBOUNDED_FRAME",
+ csid_hw->hw_intf->hw_idx);
+ csid_hw->error_irq_count++;
+ }
}
+ spin_unlock_irqrestore(&csid_hw->lock_state, flags);
if (csid_hw->error_irq_count >
CAM_IFE_CSID_MAX_IRQ_ERROR_COUNT) {
@@ -3170,6 +3298,11 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d IPP EOF received",
csid_hw->hw_intf->hw_idx);
+ if ((irq_status_ipp & CSID_PATH_ERROR_CCIF_VIOLATION))
+ CAM_INFO_RATE_LIMIT(CAM_ISP,
+ "CSID:%d IPP CCIF violation",
+ csid_hw->hw_intf->hw_idx);
+
if (irq_status_ipp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
"CSID:%d IPP fifo over flow",
@@ -3203,6 +3336,11 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PPP EOF received",
csid_hw->hw_intf->hw_idx);
+ if ((irq_status_ipp & CSID_PATH_ERROR_CCIF_VIOLATION))
+ CAM_INFO_RATE_LIMIT(CAM_ISP,
+ "CSID:%d PPP CCIF violation",
+ csid_hw->hw_intf->hw_idx);
+
if (irq_status_ppp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
"CSID:%d PPP fifo over flow",
@@ -3234,6 +3372,10 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
CAM_INFO_RATE_LIMIT(CAM_ISP,
"CSID RDI:%d EOF received", i);
+ if ((irq_status_rdi[i] & CSID_PATH_ERROR_CCIF_VIOLATION))
+ CAM_INFO_RATE_LIMIT(CAM_ISP,
+ "CSIDi RDI :%d CCIF violation", i);
+
if (irq_status_rdi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
"CSID:%d RDI fifo over flow",
@@ -3280,9 +3422,11 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,
ife_csid_hw->hw_intf->hw_type, csid_idx);
+ ife_csid_hw->device_enabled = 0;
ife_csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
mutex_init(&ife_csid_hw->hw_info->hw_mutex);
spin_lock_init(&ife_csid_hw->hw_info->hw_lock);
+ spin_lock_init(&ife_csid_hw->lock_state);
init_completion(&ife_csid_hw->hw_info->hw_complete);
init_completion(&ife_csid_hw->csid_top_complete);
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
index 43fd9b03132e..3a093d205f59 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -64,6 +64,7 @@
#define CSID_PATH_INFO_INPUT_SOF BIT(12)
#define CSID_PATH_ERROR_PIX_COUNT BIT(13)
#define CSID_PATH_ERROR_LINE_COUNT BIT(14)
+#define CSID_PATH_ERROR_CCIF_VIOLATION BIT(15)
/*
* Debug values enable the corresponding interrupts and debug logs provide
@@ -138,6 +139,8 @@ struct cam_ife_csid_pxl_reg_offset {
/* configuration */
uint32_t pix_store_en_shift_val;
uint32_t early_eof_en_shift_val;
+ uint32_t quad_cfa_bin_en_shift_val;
+ uint32_t ccif_violation_en;
};
struct cam_ife_csid_rdi_reg_offset {
@@ -182,6 +185,10 @@ struct cam_ife_csid_rdi_reg_offset {
uint32_t csid_rdi_timestamp_prev1_eof_addr;
uint32_t csid_rdi_byte_cntr_ping_addr;
uint32_t csid_rdi_byte_cntr_pong_addr;
+
+ /* configuration */
+ uint32_t packing_format;
+ uint32_t ccif_violation_en;
};
struct cam_ife_csid_csi2_rx_reg_offset {
@@ -194,7 +201,7 @@ struct cam_ife_csid_csi2_rx_reg_offset {
uint32_t csid_csi2_rx_capture_ctrl_addr;
uint32_t csid_csi2_rx_rst_strobes_addr;
uint32_t csid_csi2_rx_de_scramble_cfg0_addr;
- uint32_t csid_csi2_rx_de_scramble_cfg1_addr; /* */
+ uint32_t csid_csi2_rx_de_scramble_cfg1_addr;
uint32_t csid_csi2_rx_cap_unmap_long_pkt_hdr_0_addr;
uint32_t csid_csi2_rx_cap_unmap_long_pkt_hdr_1_addr;
uint32_t csid_csi2_rx_captured_short_pkt_0_addr;
@@ -210,6 +217,14 @@ struct cam_ife_csid_csi2_rx_reg_offset {
uint32_t csid_csi2_rx_total_pkts_rcvd_addr;
uint32_t csid_csi2_rx_stats_ecc_addr;
uint32_t csid_csi2_rx_total_crc_err_addr;
+ uint32_t csid_csi2_rx_de_scramble_type3_cfg0_addr;
+ uint32_t csid_csi2_rx_de_scramble_type3_cfg1_addr;
+ uint32_t csid_csi2_rx_de_scramble_type2_cfg0_addr;
+ uint32_t csid_csi2_rx_de_scramble_type2_cfg1_addr;
+ uint32_t csid_csi2_rx_de_scramble_type1_cfg0_addr;
+ uint32_t csid_csi2_rx_de_scramble_type1_cfg1_addr;
+ uint32_t csid_csi2_rx_de_scramble_type0_cfg0_addr;
+ uint32_t csid_csi2_rx_de_scramble_type0_cfg1_addr;
/*configurations */
uint32_t csi2_rst_srb_all;
@@ -225,6 +240,7 @@ struct cam_ife_csid_csi2_rx_reg_offset {
uint32_t csi2_capture_short_pkt_vc_shift;
uint32_t csi2_capture_cphy_pkt_dt_shift;
uint32_t csi2_capture_cphy_pkt_vc_shift;
+ uint32_t csi2_rx_phy_num_mask;
};
struct cam_ife_csid_csi2_tpg_reg_offset {
@@ -274,6 +290,7 @@ struct cam_ife_csid_common_reg_offset {
uint32_t num_rdis;
uint32_t num_pix;
uint32_t num_ppp;
+ uint32_t csid_reg_rst_stb;
uint32_t csid_rst_stb;
uint32_t csid_rst_stb_sw_all;
uint32_t path_rst_stb_all;
@@ -477,6 +494,8 @@ struct cam_ife_csid_hw {
bool sof_irq_triggered;
uint32_t irq_debug_cnt;
uint32_t error_irq_count;
+ uint32_t device_enabled;
+ spinlock_t lock_state;
};
int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.c
deleted file mode 100644
index 6c39bd84e47f..000000000000
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include "cam_ife_csid_lite170.h"
-#include "cam_ife_csid_core.h"
-#include "cam_ife_csid_dev.h"
-
-#define CAM_CSID_LITE_DRV_NAME "csid_lite_170"
-#define CAM_CSID_LITE_VERSION_V170 0x10070000
-
-static struct cam_ife_csid_hw_info cam_ife_csid_lite170_hw_info = {
- .csid_reg = &cam_ife_csid_lite_170_reg_offset,
- .hw_dts_version = CAM_CSID_LITE_VERSION_V170,
-};
-
-static const struct of_device_id cam_ife_csid_lite170_dt_match[] = {
- {
- .compatible = "qcom,csid-lite170",
- .data = &cam_ife_csid_lite170_hw_info,
- },
- {}
-};
-MODULE_DEVICE_TABLE(of, cam_ife_csid_lite170_dt_match);
-
-static struct platform_driver cam_ife_csid_lite170_driver = {
- .probe = cam_ife_csid_probe,
- .remove = cam_ife_csid_remove,
- .driver = {
- .name = CAM_CSID_LITE_DRV_NAME,
- .owner = THIS_MODULE,
- .of_match_table = cam_ife_csid_lite170_dt_match,
- .suppress_bind_attrs = true,
- },
-};
-
-static int __init cam_ife_csid_lite170_init_module(void)
-{
- return platform_driver_register(&cam_ife_csid_lite170_driver);
-}
-
-static void __exit cam_ife_csid_lite170_exit_module(void)
-{
- platform_driver_unregister(&cam_ife_csid_lite170_driver);
-}
-
-module_init(cam_ife_csid_lite170_init_module);
-module_exit(cam_ife_csid_lite170_exit_module);
-MODULE_DESCRIPTION("CAM IFE_CSID_LITE170 driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c
index b05a4b533c23..11c71145ef94 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -26,6 +26,10 @@ static const struct of_device_id cam_ife_csid_lite_dt_match[] = {
.compatible = "qcom,csid-lite170",
.data = &cam_ife_csid_lite_hw_info,
},
+ {
+ .compatible = "qcom,csid-lite175",
+ .data = &cam_ife_csid_lite_hw_info,
+ },
{}
};
MODULE_DEVICE_TABLE(of, cam_ife_csid_lite_dt_match);
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h
index d4e05115455a..e39666fe12b7 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -232,6 +232,7 @@ static const struct cam_ife_csid_csi2_rx_reg_offset
.csi2_capture_short_pkt_vc_shift = 15,
.csi2_capture_cphy_pkt_dt_shift = 20,
.csi2_capture_cphy_pkt_vc_shift = 26,
+ .csi2_rx_phy_num_mask = 0x3,
};
@@ -286,6 +287,7 @@ static const struct cam_ife_csid_common_reg_offset
.version_incr = 0,
.num_rdis = 4,
.num_pix = 0,
+ .csid_reg_rst_stb = 1,
.csid_rst_stb = 0x1e,
.csid_rst_stb_sw_all = 0x1f,
.path_rst_stb_all = 0x7f,
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
index 940d338a9572..61542566a924 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -80,14 +80,17 @@ enum cam_isp_resource_type {
CAM_ISP_RESOURCE_PIX_PATH,
CAM_ISP_RESOURCE_VFE_IN,
CAM_ISP_RESOURCE_VFE_OUT,
+ CAM_ISP_RESOURCE_VFE_BUS_RD,
CAM_ISP_RESOURCE_MAX,
};
enum cam_isp_hw_cmd_type {
CAM_ISP_HW_CMD_GET_CHANGE_BASE,
CAM_ISP_HW_CMD_GET_BUF_UPDATE,
+ CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM,
CAM_ISP_HW_CMD_GET_REG_UPDATE,
CAM_ISP_HW_CMD_GET_HFR_UPDATE,
+ CAM_ISP_HW_CMD_GET_HFR_UPDATE_RM,
CAM_ISP_HW_CMD_GET_SECURE_MODE,
CAM_ISP_HW_CMD_STRIPE_UPDATE,
CAM_ISP_HW_CMD_CLOCK_UPDATE,
@@ -95,10 +98,12 @@ enum cam_isp_hw_cmd_type {
CAM_ISP_HW_CMD_BW_CONTROL,
CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ,
CAM_ISP_HW_CMD_GET_REG_DUMP,
+ CAM_ISP_HW_CMD_UBWC_UPDATE,
CAM_ISP_HW_CMD_SOF_IRQ_DEBUG,
CAM_ISP_HW_CMD_SET_CAMIF_DEBUG,
- CAM_ISP_HW_CMD_UBWC_UPDATE,
CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE,
+ CAM_ISP_HW_CMD_FE_UPDATE_IN_RD,
+ CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD,
CAM_ISP_HW_CMD_MAX,
};
@@ -186,6 +191,20 @@ struct cam_isp_hw_get_wm_update {
};
/*
+ * struct cam_isp_hw_rup_data:
+ *
+ * @Brief: RUP for required resources.
+ *
+ * @is_fe_enable if fetch engine enabled
+ * @res_bitmap resource bitmap for set resources
+ *
+ */
+struct cam_isp_hw_rup_data {
+ bool is_fe_enable;
+ unsigned long res_bitmap;
+};
+
+/*
* struct cam_isp_hw_get_cmd_update:
*
* @Brief: Get cmd buffer update for different CMD types
@@ -202,10 +221,13 @@ struct cam_isp_hw_get_cmd_update {
union {
void *data;
struct cam_isp_hw_get_wm_update *wm_update;
+ struct cam_isp_hw_get_wm_update *rm_update;
struct cam_isp_port_hfr_config *hfr_update;
struct cam_isp_clock_config *clock_update;
struct cam_isp_bw_config *bw_update;
struct cam_ubwc_plane_cfg_v1 *ubwc_update;
+ struct cam_fe_config *fe_update;
+ struct cam_isp_hw_rup_data *rup_data;
};
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
index b957d6913f77..f60bf6e4b3d4 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -28,7 +28,7 @@
enum cam_isp_hw_vfe_in_mux {
CAM_ISP_HW_VFE_IN_CAMIF = 0,
CAM_ISP_HW_VFE_IN_TESTGEN = 1,
- CAM_ISP_HW_VFE_IN_BUS_RD = 2,
+ CAM_ISP_HW_VFE_IN_RD = 2,
CAM_ISP_HW_VFE_IN_RDI0 = 3,
CAM_ISP_HW_VFE_IN_RDI1 = 4,
CAM_ISP_HW_VFE_IN_RDI2 = 5,
@@ -153,6 +153,7 @@ struct cam_vfe_hw_vfe_in_acquire_args {
* used to schedule bottom of IRQ events associated
* with this resource.
* @vfe_out: Acquire args for VFE_OUT
+ * @vfe_bus_rd Acquire args for VFE_BUS_READ
* @vfe_in: Acquire args for VFE_IN
*/
struct cam_vfe_acquire_args {
@@ -160,6 +161,7 @@ struct cam_vfe_acquire_args {
void *tasklet;
union {
struct cam_vfe_hw_vfe_out_acquire_args vfe_out;
+ struct cam_vfe_hw_vfe_out_acquire_args vfe_bus_rd;
struct cam_vfe_hw_vfe_in_acquire_args vfe_in;
};
};
@@ -178,7 +180,7 @@ struct cam_vfe_clock_update_args {
/*
* struct cam_vfe_bw_update_args:
*
- * @node_res: Resource to get the time stamp
+ * @node_res: Resource to get the BW
* @camnoc_bw_bytes: Bandwidth vote request for CAMNOC
* @external_bw_bytes: Bandwidth vote request from CAMNOC
* out to the rest of the path-to-DDR
@@ -189,6 +191,18 @@ struct cam_vfe_bw_update_args {
uint64_t external_bw_bytes;
};
+/*
+ * struct cam_vfe_fe_update_args:
+ *
+ * @node_res: Resource to get fetch configuration
+ * @fe_config: fetch engine configuration
+ *
+ */
+struct cam_vfe_fe_update_args {
+ struct cam_isp_resource_node *node_res;
+ struct cam_fe_config fe_config;
+};
+
enum cam_vfe_bw_control_action {
CAM_VFE_BW_CONTROL_EXCLUDE = 0,
CAM_VFE_BW_CONTROL_INCLUDE = 1
@@ -218,6 +232,7 @@ struct cam_vfe_bw_control_args {
* @irq_reg_val: IRQ and Error register values, read when IRQ was
* handled
* @error_type: Identify different errors
+ * @enable_reg_dump: enable register dump on error
* @ts: Timestamp
*/
struct cam_vfe_top_irq_evt_payload {
@@ -227,6 +242,7 @@ struct cam_vfe_top_irq_evt_payload {
uint32_t evt_id;
uint32_t irq_reg_val[CAM_IFE_IRQ_REGISTERS_MAX];
uint32_t error_type;
+ bool enable_reg_dump;
struct cam_isp_timestamp ts;
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
index 5e6bb2012fff..2bd6db9954f1 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -36,6 +36,11 @@ static uint32_t camif_irq_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {
0x00000000,
};
+static uint32_t camif_fe_irq_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {
+ 0x10000056,
+ 0x00000000,
+};
+
static uint32_t camif_irq_err_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {
0x0003FC00,
0xEFFF7EBC,
@@ -286,6 +291,16 @@ int cam_vfe_init_hw(void *hw_priv, void *init_hw_args, uint32_t arg_size)
goto deinint_vfe_res;
}
+ if (core_info->vfe_rd_bus) {
+ rc = core_info->vfe_rd_bus->hw_ops.init(
+ core_info->vfe_rd_bus->bus_priv,
+ NULL, 0);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Bus RD HW init Failed rc=%d", rc);
+ goto deinint_vfe_res;
+ }
+ }
+
vfe_hw->hw_state = CAM_HW_STATE_POWER_UP;
return rc;
@@ -339,6 +354,14 @@ int cam_vfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size)
if (rc)
CAM_ERR(CAM_ISP, "Bus HW deinit Failed rc=%d", rc);
+ if (core_info->vfe_rd_bus) {
+ rc = core_info->vfe_rd_bus->hw_ops.deinit(
+ core_info->vfe_rd_bus->bus_priv,
+ NULL, 0);
+ if (rc)
+ CAM_ERR(CAM_ISP, "Bus HW deinit Failed rc=%d", rc);
+ }
+
isp_res = (struct cam_isp_resource_node *)deinit_hw_args;
if (isp_res && isp_res->deinit) {
rc = isp_res->deinit(isp_res, NULL, 0);
@@ -485,18 +508,25 @@ int cam_vfe_reserve(void *hw_priv, void *reserve_args, uint32_t arg_size)
core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info;
acquire = (struct cam_vfe_acquire_args *)reserve_args;
+ CAM_DBG(CAM_ISP, "acq res type: %d", acquire->rsrc_type);
mutex_lock(&vfe_hw->hw_mutex);
- if (acquire->rsrc_type == CAM_ISP_RESOURCE_VFE_IN)
+ if (acquire->rsrc_type == CAM_ISP_RESOURCE_VFE_IN) {
rc = core_info->vfe_top->hw_ops.reserve(
core_info->vfe_top->top_priv,
acquire,
sizeof(*acquire));
- else if (acquire->rsrc_type == CAM_ISP_RESOURCE_VFE_OUT)
+ } else if (acquire->rsrc_type == CAM_ISP_RESOURCE_VFE_OUT) {
rc = core_info->vfe_bus->hw_ops.reserve(
core_info->vfe_bus->bus_priv, acquire,
sizeof(*acquire));
- else
+ } else if (acquire->rsrc_type == CAM_ISP_RESOURCE_VFE_BUS_RD) {
+ if (core_info->vfe_rd_bus)
+ rc = core_info->vfe_rd_bus->hw_ops.reserve(
+ core_info->vfe_rd_bus->bus_priv, acquire,
+ sizeof(*acquire));
+ } else {
CAM_ERR(CAM_ISP, "Invalid res type:%d", acquire->rsrc_type);
+ }
mutex_unlock(&vfe_hw->hw_mutex);
@@ -529,8 +559,14 @@ int cam_vfe_release(void *hw_priv, void *release_args, uint32_t arg_size)
rc = core_info->vfe_bus->hw_ops.release(
core_info->vfe_bus->bus_priv, isp_res,
sizeof(*isp_res));
- else
+ else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_BUS_RD) {
+ if (core_info->vfe_rd_bus)
+ rc = core_info->vfe_rd_bus->hw_ops.release(
+ core_info->vfe_rd_bus->bus_priv, isp_res,
+ sizeof(*isp_res));
+ } else {
CAM_ERR(CAM_ISP, "Invalid res type:%d", isp_res->res_type);
+ }
mutex_unlock(&vfe_hw->hw_mutex);
@@ -570,6 +606,19 @@ int cam_vfe_start(void *hw_priv, void *start_args, uint32_t arg_size)
&tasklet_bh_api);
if (isp_res->irq_handle < 1)
rc = -ENOMEM;
+ } else if (isp_res->res_id == CAM_ISP_HW_VFE_IN_RD) {
+ isp_res->irq_handle =
+ cam_irq_controller_subscribe_irq(
+ core_info->vfe_irq_controller,
+ CAM_IRQ_PRIORITY_1,
+ camif_fe_irq_reg_mask,
+ &core_info->irq_payload,
+ cam_vfe_irq_top_half,
+ cam_ife_mgr_do_tasklet,
+ isp_res->tasklet_info,
+ &tasklet_bh_api);
+ if (isp_res->irq_handle < 1)
+ rc = -ENOMEM;
} else if (isp_res->rdi_only_ctx) {
isp_res->irq_handle =
cam_irq_controller_subscribe_irq(
@@ -598,6 +647,10 @@ int cam_vfe_start(void *hw_priv, void *start_args, uint32_t arg_size)
}
} else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_OUT) {
rc = core_info->vfe_bus->hw_ops.start(isp_res, NULL, 0);
+ } else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_BUS_RD) {
+ if (core_info->vfe_rd_bus)
+ rc = core_info->vfe_rd_bus->hw_ops.start(isp_res,
+ NULL, 0);
} else {
CAM_ERR(CAM_ISP, "Invalid res type:%d", isp_res->res_type);
rc = -EFAULT;
@@ -653,6 +706,10 @@ int cam_vfe_stop(void *hw_priv, void *stop_args, uint32_t arg_size)
sizeof(struct cam_isp_resource_node));
} else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_OUT) {
rc = core_info->vfe_bus->hw_ops.stop(isp_res, NULL, 0);
+ } else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_BUS_RD) {
+ if (core_info->vfe_rd_bus)
+ rc = core_info->vfe_rd_bus->hw_ops.stop(isp_res,
+ NULL, 0);
} else {
CAM_ERR(CAM_ISP, "Invalid res type:%d", isp_res->res_type);
}
@@ -716,7 +773,26 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
core_info->vfe_bus->bus_priv, cmd_type, cmd_args,
arg_size);
break;
+ case CAM_ISP_HW_CMD_GET_HFR_UPDATE_RM:
+ case CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM:
+ if (core_info->vfe_rd_bus)
+ rc = core_info->vfe_rd_bus->hw_ops.process_cmd(
+ core_info->vfe_rd_bus->bus_priv, cmd_type,
+ cmd_args, arg_size);
+ break;
+ case CAM_ISP_HW_CMD_FE_UPDATE_IN_RD:
+ rc = core_info->vfe_top->hw_ops.process_cmd(
+ core_info->vfe_top->top_priv, cmd_type, cmd_args,
+ arg_size);
+ break;
+ case CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD:
+ if (core_info->vfe_rd_bus) {
+ rc = core_info->vfe_rd_bus->hw_ops.process_cmd(
+ core_info->vfe_rd_bus->bus_priv, cmd_type,
+ cmd_args, arg_size);
+ }
+ break;
default:
CAM_ERR(CAM_ISP, "Invalid cmd type:%d", cmd_type);
rc = -EINVAL;
@@ -766,7 +842,8 @@ int cam_vfe_core_init(struct cam_vfe_hw_core_info *core_info,
goto deinit_controller;
}
- rc = cam_vfe_bus_init(vfe_hw_info->bus_version, soc_info, hw_intf,
+ rc = cam_vfe_bus_init(vfe_hw_info->bus_version, BUS_TYPE_WR,
+ soc_info, hw_intf,
vfe_hw_info->bus_hw_info, core_info->vfe_irq_controller,
&core_info->vfe_bus);
if (rc) {
@@ -774,6 +851,19 @@ int cam_vfe_core_init(struct cam_vfe_hw_core_info *core_info,
goto deinit_top;
}
+ /* Read Bus is not valid for vfe-lite */
+ if ((hw_intf->hw_idx == 0) || (hw_intf->hw_idx == 1)) {
+ rc = cam_vfe_bus_init(vfe_hw_info->bus_rd_version, BUS_TYPE_RD,
+ soc_info, hw_intf, vfe_hw_info->bus_rd_hw_info,
+ core_info->vfe_irq_controller, &core_info->vfe_rd_bus);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Error! RD cam_vfe_bus_init failed");
+ rc = 0;
+ }
+ CAM_DBG(CAM_ISP, "vfe_bus_rd %pK hw_idx %d",
+ core_info->vfe_rd_bus, hw_intf->hw_idx);
+ }
+
INIT_LIST_HEAD(&core_info->free_payload_list);
for (i = 0; i < CAM_VFE_EVT_MAX; i++) {
INIT_LIST_HEAD(&core_info->evt_payload[i].list);
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h
index 9cec56a15fec..dd078f2d6ce3 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -25,6 +25,9 @@ struct cam_vfe_hw_info {
uint32_t bus_version;
void *bus_hw_info;
+ uint32_t bus_rd_version;
+ void *bus_rd_hw_info;
+
uint32_t top_version;
void *top_hw_info;
uint32_t camif_version;
@@ -53,6 +56,7 @@ struct cam_vfe_hw_core_info {
void *vfe_irq_controller;
struct cam_vfe_top *vfe_top;
struct cam_vfe_bus *vfe_bus;
+ struct cam_vfe_bus *vfe_rd_bus;
void *tasklet_info;
struct cam_vfe_top_irq_evt_payload evt_payload[CAM_VFE_EVT_MAX];
struct list_head free_payload_list;
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
index 12b7a03c6276..b57762644082 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -26,6 +26,8 @@ static bool cam_vfe_cpas_cb(uint32_t client_handle, void *userdata,
switch (irq_data->irq_type) {
case CAM_CAMNOC_IRQ_IFE02_UBWC_ENCODE_ERROR:
case CAM_CAMNOC_IRQ_IFE13_UBWC_ENCODE_ERROR:
+ case CAM_CAMNOC_IRQ_IFE0_UBWC_ENCODE_ERROR:
+ case CAM_CAMNOC_IRQ_IFE1_WRITE_UBWC_ENCODE_ERROR:
CAM_ERR_RATE_LIMIT(CAM_ISP,
"IFE UBWC Encode error type=%d status=%x",
irq_data->irq_type,
@@ -104,7 +106,7 @@ int cam_vfe_init_soc_resources(struct cam_hw_soc_info *soc_info,
CAM_VFE_DSP_CLK_NAME, &soc_private->dsp_clk,
&soc_private->dsp_clk_index, &soc_private->dsp_clk_rate);
if (rc)
- CAM_WARN(CAM_ISP, "option clk get failed");
+ CAM_WARN(CAM_ISP, "Option clk get failed with rc %d", rc);
rc = cam_vfe_request_platform_resource(soc_info, vfe_irq_handler,
irq_data);
@@ -115,20 +117,56 @@ int cam_vfe_init_soc_resources(struct cam_hw_soc_info *soc_info,
}
memset(&cpas_register_param, 0, sizeof(cpas_register_param));
- strlcpy(cpas_register_param.identifier, "ife",
- CAM_HW_IDENTIFIER_LENGTH);
+
cpas_register_param.cell_index = soc_info->index;
cpas_register_param.dev = soc_info->dev;
cpas_register_param.cam_cpas_client_cb = cam_vfe_cpas_cb;
cpas_register_param.userdata = soc_info;
- rc = cam_cpas_register_client(&cpas_register_param);
+
+ rc = cam_cpas_get_cpas_hw_version(&soc_private->cpas_version);
if (rc) {
- CAM_ERR(CAM_ISP, "CPAS registration failed rc=%d", rc);
- goto release_soc;
- } else {
- soc_private->cpas_handle = cpas_register_param.client_handle;
+ CAM_ERR(CAM_ISP, "Error! Invalid cpas version rc=%d", rc);
+ goto free_soc_private;
}
+ switch (soc_private->cpas_version) {
+ case CAM_CPAS_TITAN_175_V120:
+ strlcpy(cpas_register_param.identifier, "iferdi",
+ CAM_HW_IDENTIFIER_LENGTH);
+ rc = cam_cpas_register_client(&cpas_register_param);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "rdi CPAS registration failed rc=%d",
+ rc);
+ goto release_soc;
+ } else {
+ soc_private->cpas_handle[0] =
+ cpas_register_param.client_handle;
+ }
+
+ strlcpy(cpas_register_param.identifier, "ifenrdi",
+ CAM_HW_IDENTIFIER_LENGTH);
+ rc = cam_cpas_register_client(&cpas_register_param);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "nrdi CPAS registration failed rc=%d",
+ rc);
+ goto release_soc;
+ } else {
+ soc_private->cpas_handle[1] =
+ cpas_register_param.client_handle;
+ }
+ break;
+ default:
+ strlcpy(cpas_register_param.identifier, "ife",
+ CAM_HW_IDENTIFIER_LENGTH);
+ rc = cam_cpas_register_client(&cpas_register_param);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "CPAS registration failed rc=%d", rc);
+ goto release_soc;
+ } else {
+ soc_private->cpas_handle[0] =
+ cpas_register_param.client_handle;
+ }
+ }
return rc;
release_soc:
@@ -154,10 +192,15 @@ int cam_vfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info)
CAM_ERR(CAM_ISP, "Error! soc_private NULL");
return -ENODEV;
}
-
- rc = cam_cpas_unregister_client(soc_private->cpas_handle);
+ rc = cam_cpas_unregister_client(soc_private->cpas_handle[0]);
if (rc)
- CAM_ERR(CAM_ISP, "CPAS unregistration failed rc=%d", rc);
+ CAM_ERR(CAM_ISP, "CPAS0 unregistration failed rc=%d", rc);
+
+ if (!rc && soc_private->cpas_version == CAM_CPAS_TITAN_175_V120)
+ rc = cam_cpas_unregister_client(soc_private->cpas_handle[1]);
+ if (rc)
+ CAM_ERR(CAM_ISP, "CPAS1 unregistration failed rc=%d",
+ rc);
rc = cam_vfe_release_platform_resource(soc_info);
if (rc < 0)
@@ -194,13 +237,22 @@ int cam_vfe_enable_soc_resources(struct cam_hw_soc_info *soc_info)
axi_vote.compressed_bw = 10640000000L;
axi_vote.uncompressed_bw = 10640000000L;
- rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote);
+ rc = cam_cpas_start(soc_private->cpas_handle[0], &ahb_vote, &axi_vote);
if (rc) {
- CAM_ERR(CAM_ISP, "Error! CPAS start failed rc=%d", rc);
+ CAM_ERR(CAM_ISP, "Error! CPAS0 start failed rc=%d", rc);
rc = -EFAULT;
goto end;
}
+ if (!rc && soc_private->cpas_version == CAM_CPAS_TITAN_175_V120)
+ rc = cam_cpas_start(soc_private->cpas_handle[1], &ahb_vote,
+ &axi_vote);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Error! CPAS1 start failed rc=%d", rc);
+ rc = -EFAULT;
+ goto end;
+ }
+
rc = cam_soc_util_enable_platform_resource(soc_info, true,
CAM_TURBO_VOTE, true);
if (rc) {
@@ -211,7 +263,9 @@ int cam_vfe_enable_soc_resources(struct cam_hw_soc_info *soc_info)
return rc;
stop_cpas:
- cam_cpas_stop(soc_private->cpas_handle);
+ cam_cpas_stop(soc_private->cpas_handle[0]);
+ if (soc_private->cpas_version == CAM_CPAS_TITAN_175_V120)
+ cam_cpas_stop(soc_private->cpas_handle[1]);
end:
return rc;
}
@@ -283,11 +337,18 @@ int cam_vfe_disable_soc_resources(struct cam_hw_soc_info *soc_info)
return rc;
}
- rc = cam_cpas_stop(soc_private->cpas_handle);
+ rc = cam_cpas_stop(soc_private->cpas_handle[0]);
if (rc) {
CAM_ERR(CAM_ISP, "Error! CPAS stop failed rc=%d", rc);
return rc;
}
+ if (!rc && soc_private->cpas_version == CAM_CPAS_TITAN_175_V120)
+ rc = cam_cpas_stop(soc_private->cpas_handle[1]);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Error! CPAS stop failed rc=%d", rc);
+ return rc;
+ }
+
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h
index 3f862e9249f8..780bd34ab968 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -18,6 +18,12 @@
#define CAM_VFE_DSP_CLK_NAME "ife_dsp_clk"
+enum cam_cpas_handle_id {
+ CAM_CPAS_HANDLE_CAMIF,
+ CAM_CPAS_HANDLE_RAW,
+ CAM_CPAS_HANDLE_MAX,
+};
+
/*
* struct cam_vfe_soc_private:
*
@@ -26,9 +32,11 @@
* @cpas_handle: Handle returned on registering with CPAS driver.
* This handle is used for all further interface
* with CPAS.
+ * @cpas_version: Has cpas version read from Hardware
*/
struct cam_vfe_soc_private {
- uint32_t cpas_handle;
+ uint32_t cpas_handle[CAM_CPAS_HANDLE_MAX];
+ uint32_t cpas_version;
struct clk *dsp_clk;
int32_t dsp_clk_index;
int32_t dsp_clk_rate;
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/Makefile b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/Makefile
deleted file mode 100644
index deeae35cef79..000000000000
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_utils
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_core
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/include
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/include
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/include
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw
-
-obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe170.o cam_vfe_lite170.o
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c
deleted file mode 100644
index d002f84015de..000000000000
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include "cam_vfe170.h"
-#include "cam_vfe_hw_intf.h"
-#include "cam_vfe_core.h"
-#include "cam_vfe_dev.h"
-
-static const struct of_device_id cam_vfe170_dt_match[] = {
- {
- .compatible = "qcom,vfe170",
- .data = &cam_vfe170_hw_info,
- },
- {}
-};
-MODULE_DEVICE_TABLE(of, cam_vfe170_dt_match);
-
-static struct platform_driver cam_vfe170_driver = {
- .probe = cam_vfe_probe,
- .remove = cam_vfe_remove,
- .driver = {
- .name = "cam_vfe170",
- .owner = THIS_MODULE,
- .of_match_table = cam_vfe170_dt_match,
- .suppress_bind_attrs = true,
- },
-};
-
-static int __init cam_vfe170_init_module(void)
-{
- return platform_driver_register(&cam_vfe170_driver);
-}
-
-static void __exit cam_vfe170_exit_module(void)
-{
- platform_driver_unregister(&cam_vfe170_driver);
-}
-
-module_init(cam_vfe170_init_module);
-module_exit(cam_vfe170_exit_module);
-MODULE_DESCRIPTION("CAM VFE170 driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.c
deleted file mode 100644
index ab692cf095e4..000000000000
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include "cam_vfe_lite170.h"
-#include "cam_vfe_hw_intf.h"
-#include "cam_vfe_core.h"
-#include "cam_vfe_dev.h"
-
-static const struct of_device_id cam_vfe170_dt_match[] = {
- {
- .compatible = "qcom,vfe-lite170",
- .data = &cam_vfe_lite170_hw_info,
- },
- {}
-};
-MODULE_DEVICE_TABLE(of, cam_vfe170_dt_match);
-
-static struct platform_driver cam_vfe170_driver = {
- .probe = cam_vfe_probe,
- .remove = cam_vfe_remove,
- .driver = {
- .name = "cam_vfe_lite170",
- .owner = THIS_MODULE,
- .of_match_table = cam_vfe170_dt_match,
- .suppress_bind_attrs = true,
- },
-};
-
-static int __init cam_vfe170_init_module(void)
-{
- return platform_driver_register(&cam_vfe170_driver);
-}
-
-static void __exit cam_vfe170_exit_module(void)
-{
- platform_driver_unregister(&cam_vfe170_driver);
-}
-
-module_init(cam_vfe170_init_module);
-module_exit(cam_vfe170_exit_module);
-MODULE_DESCRIPTION("CAM VFE170 driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.h
deleted file mode 100644
index 4b2e0963a599..000000000000
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.h
+++ /dev/null
@@ -1,336 +0,0 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _CAM_VFE_LITE170_H_
-#define _CAM_VFE_LITE170_H_
-
-#include "cam_vfe_bus_ver2.h"
-#include "cam_irq_controller.h"
-#include "cam_vfe_top_ver2.h"
-#include "cam_vfe_core.h"
-
-static struct cam_irq_register_set vfe170_top_irq_reg_set[2] = {
- {
- .mask_reg_offset = 0x0000005C,
- .clear_reg_offset = 0x00000064,
- .status_reg_offset = 0x0000006C,
- },
- {
- .mask_reg_offset = 0x00000060,
- .clear_reg_offset = 0x00000068,
- .status_reg_offset = 0x00000070,
- },
-};
-
-static struct cam_irq_controller_reg_info vfe170_top_irq_reg_info = {
- .num_registers = 2,
- .irq_reg_set = vfe170_top_irq_reg_set,
- .global_clear_offset = 0x00000058,
- .global_clear_bitmask = 0x00000001,
-};
-
-static struct cam_vfe_top_ver2_reg_offset_common vfe170_top_common_reg = {
- .hw_version = 0x00000000,
- .hw_capability = 0x00000004,
- .lens_feature = 0x00000008,
- .stats_feature = 0x0000000C,
- .color_feature = 0x00000010,
- .zoom_feature = 0x00000014,
- .global_reset_cmd = 0x00000018,
- .module_ctrl = {
- NULL,
- NULL,
- NULL,
- NULL,
- },
- .bus_cgc_ovd = 0x0000003C,
- .core_cfg = 0x00000000,
- .three_D_cfg = 0x00000000,
- .violation_status = 0x0000007C,
- .reg_update_cmd = 0x000004AC,
-};
-
-static struct cam_vfe_rdi_ver2_reg vfe170_rdi_reg = {
- .reg_update_cmd = 0x000004AC,
-};
-
-static struct cam_vfe_rdi_reg_data vfe170_rdi_0_data = {
- .reg_update_cmd_data = 0x2,
- .sof_irq_mask = 0x8000000,
- .reg_update_irq_mask = 0x20,
-};
-
-static struct cam_vfe_rdi_reg_data vfe170_rdi_1_data = {
- .reg_update_cmd_data = 0x4,
- .sof_irq_mask = 0x10000000,
- .reg_update_irq_mask = 0x40,
-};
-
-static struct cam_vfe_rdi_reg_data vfe170_rdi_2_data = {
- .reg_update_cmd_data = 0x8,
- .sof_irq_mask = 0x20000000,
- .reg_update_irq_mask = 0x80,
-};
-
-static struct cam_vfe_rdi_reg_data vfe170_rdi_3_data = {
- .reg_update_cmd_data = 0x10,
- .sof_irq_mask = 0x40000000,
- .reg_update_irq_mask = 0x100,
-};
-
-static struct cam_vfe_top_ver2_hw_info vfe170_top_hw_info = {
- .common_reg = &vfe170_top_common_reg,
- .camif_hw_info = {
- .common_reg = NULL,
- .camif_reg = NULL,
- .reg_data = NULL,
- },
- .rdi_hw_info = {
- .common_reg = &vfe170_top_common_reg,
- .rdi_reg = &vfe170_rdi_reg,
- .reg_data = {
- &vfe170_rdi_0_data,
- &vfe170_rdi_1_data,
- &vfe170_rdi_2_data,
- &vfe170_rdi_3_data,
- },
- },
- .mux_type = {
- CAM_VFE_RDI_VER_1_0,
- CAM_VFE_RDI_VER_1_0,
- CAM_VFE_RDI_VER_1_0,
- CAM_VFE_RDI_VER_1_0,
- },
-};
-
-static struct cam_irq_register_set vfe170_bus_irq_reg[3] = {
- {
- .mask_reg_offset = 0x00002044,
- .clear_reg_offset = 0x00002050,
- .status_reg_offset = 0x0000205C,
- },
- {
- .mask_reg_offset = 0x00002048,
- .clear_reg_offset = 0x00002054,
- .status_reg_offset = 0x00002060,
- },
- {
- .mask_reg_offset = 0x0000204C,
- .clear_reg_offset = 0x00002058,
- .status_reg_offset = 0x00002064,
- },
-};
-
-static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
- .common_reg = {
- .hw_version = 0x00002000,
- .hw_capability = 0x00002004,
- .sw_reset = 0x00002008,
- .cgc_ovd = 0x0000200C,
- .pwr_iso_cfg = 0x000020CC,
- .dual_master_comp_cfg = 0x00002028,
- .irq_reg_info = {
- .num_registers = 3,
- .irq_reg_set = vfe170_bus_irq_reg,
- .global_clear_offset = 0x00002068,
- .global_clear_bitmask = 0x00000001,
- },
- .comp_error_status = 0x0000206C,
- .comp_ovrwr_status = 0x00002070,
- .dual_comp_error_status = 0x00002074,
- .dual_comp_ovrwr_status = 0x00002078,
- .addr_sync_cfg = 0x0000207C,
- .addr_sync_frame_hdr = 0x00002080,
- .addr_sync_no_sync = 0x00002084,
- },
- .num_client = 4,
- .bus_client_reg = {
- /* BUS Client 0 */
- {
- .status0 = 0x00002200,
- .status1 = 0x00002204,
- .cfg = 0x00002208,
- .header_addr = 0x0000220C,
- .header_cfg = 0x00002210,
- .image_addr = 0x00002214,
- .image_addr_offset = 0x00002218,
- .buffer_width_cfg = 0x0000221C,
- .buffer_height_cfg = 0x00002220,
- .packer_cfg = 0x00002224,
- .stride = 0x00002228,
- .irq_subsample_period = 0x00002248,
- .irq_subsample_pattern = 0x0000224C,
- .framedrop_period = 0x00002250,
- .framedrop_pattern = 0x00002254,
- .frame_inc = 0x00002258,
- .burst_limit = 0x0000225C,
- .ubwc_regs = NULL,
- },
- /* BUS Client 1 */
- {
- .status0 = 0x00002300,
- .status1 = 0x00002304,
- .cfg = 0x00002308,
- .header_addr = 0x0000230C,
- .header_cfg = 0x00002310,
- .image_addr = 0x00002314,
- .image_addr_offset = 0x00002318,
- .buffer_width_cfg = 0x0000231C,
- .buffer_height_cfg = 0x00002320,
- .packer_cfg = 0x00002324,
- .stride = 0x00002328,
- .irq_subsample_period = 0x00002348,
- .irq_subsample_pattern = 0x0000234C,
- .framedrop_period = 0x00002350,
- .framedrop_pattern = 0x00002354,
- .frame_inc = 0x00002358,
- .burst_limit = 0x0000235C,
- .ubwc_regs = NULL,
- },
- /* BUS Client 2 */
- {
- .status0 = 0x00002400,
- .status1 = 0x00002404,
- .cfg = 0x00002408,
- .header_addr = 0x0000240C,
- .header_cfg = 0x00002410,
- .image_addr = 0x00002414,
- .image_addr_offset = 0x00002418,
- .buffer_width_cfg = 0x0000241C,
- .buffer_height_cfg = 0x00002420,
- .packer_cfg = 0x00002424,
- .stride = 0x00002428,
- .irq_subsample_period = 0x00002448,
- .irq_subsample_pattern = 0x0000244C,
- .framedrop_period = 0x00002450,
- .framedrop_pattern = 0x00002454,
- .frame_inc = 0x00002458,
- .burst_limit = 0x0000245C,
- .ubwc_regs = NULL,
- },
- /* BUS Client 3 */
- {
- .status0 = 0x00002500,
- .status1 = 0x00002504,
- .cfg = 0x00002508,
- .header_addr = 0x0000250C,
- .header_cfg = 0x00002510,
- .image_addr = 0x00002514,
- .image_addr_offset = 0x00002518,
- .buffer_width_cfg = 0x0000251C,
- .buffer_height_cfg = 0x00002520,
- .packer_cfg = 0x00002524,
- .stride = 0x00002528,
- .irq_subsample_period = 0x00002548,
- .irq_subsample_pattern = 0x0000254C,
- .framedrop_period = 0x00002550,
- .framedrop_pattern = 0x00002554,
- .frame_inc = 0x00002558,
- .burst_limit = 0x0000255C,
- .ubwc_regs = NULL,
- },
- },
- .comp_grp_reg = {
- /* CAM_VFE_BUS_VER2_COMP_GRP_0 */
- {
- .comp_mask = 0x00002010,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_1 */
- {
- .comp_mask = 0x00002014,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_2 */
- {
- .comp_mask = 0x00002018,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_3 */
- {
- .comp_mask = 0x0000201C,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_4 */
- {
- .comp_mask = 0x00002020,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_5 */
- {
- .comp_mask = 0x00002024,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 */
- {
- .comp_mask = 0x0000202C,
- .addr_sync_mask = 0x00002088,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1 */
- {
- .comp_mask = 0x00002030,
- .addr_sync_mask = 0x0000208C,
-
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2 */
- {
- .comp_mask = 0x00002034,
- .addr_sync_mask = 0x00002090,
-
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3 */
- {
- .comp_mask = 0x00002038,
- .addr_sync_mask = 0x00002094,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4 */
- {
- .comp_mask = 0x0000203C,
- .addr_sync_mask = 0x00002098,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 */
- {
- .comp_mask = 0x00002040,
- .addr_sync_mask = 0x0000209C,
- },
- },
- .num_out = 4,
- .vfe_out_hw_info = {
- {
- .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI0,
- .max_width = -1,
- .max_height = -1,
- },
- {
- .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI1,
- .max_width = -1,
- .max_height = -1,
- },
- {
- .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI2,
- .max_width = -1,
- .max_height = -1,
- },
- {
- .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI3,
- .max_width = -1,
- .max_height = -1,
- },
- },
-};
-
-static struct cam_vfe_hw_info cam_vfe_lite170_hw_info = {
- .irq_reg_info = &vfe170_top_irq_reg_info,
-
- .bus_version = CAM_VFE_BUS_VER_2_0,
- .bus_hw_info = &vfe170_bus_hw_info,
-
- .top_version = CAM_VFE_TOP_VER_2_0,
- .top_hw_info = &vfe170_top_hw_info,
-
-};
-
-#endif /* _CAM_VFE_LITE170_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h
index d1284d9f23d2..b47bd0d51a28 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -10,16 +10,17 @@
* GNU General Public License for more details.
*/
-#ifndef _CAM_VFE170_H_
-#define _CAM_VFE170_H_
+#ifndef _CAM_VFE175_H_
+#define _CAM_VFE175_H_
#include "cam_vfe_camif_ver2.h"
+#include "cam_vfe_camif_lite_ver2.h"
#include "cam_vfe_bus_ver2.h"
#include "cam_irq_controller.h"
#include "cam_vfe_top_ver2.h"
#include "cam_vfe_core.h"
-static struct cam_irq_register_set vfe170_top_irq_reg_set[2] = {
+static struct cam_irq_register_set vfe175_top_irq_reg_set[2] = {
{
.mask_reg_offset = 0x0000005C,
.clear_reg_offset = 0x00000064,
@@ -32,14 +33,14 @@ static struct cam_irq_register_set vfe170_top_irq_reg_set[2] = {
},
};
-static struct cam_irq_controller_reg_info vfe170_top_irq_reg_info = {
+static struct cam_irq_controller_reg_info vfe175_top_irq_reg_info = {
.num_registers = 2,
- .irq_reg_set = vfe170_top_irq_reg_set,
+ .irq_reg_set = vfe175_top_irq_reg_set,
.global_clear_offset = 0x00000058,
.global_clear_bitmask = 0x00000001,
};
-static struct cam_vfe_camif_ver2_reg vfe170_camif_reg = {
+static struct cam_vfe_camif_ver2_reg vfe175_camif_reg = {
.camif_cmd = 0x00000478,
.camif_config = 0x0000047C,
.line_skip_pattern = 0x00000488,
@@ -54,7 +55,7 @@ static struct cam_vfe_camif_ver2_reg vfe170_camif_reg = {
.vfe_diag_sensor_status = 0x00000C4C,
};
-static struct cam_vfe_camif_reg_data vfe_170_camif_reg_data = {
+static struct cam_vfe_camif_reg_data vfe_175_camif_reg_data = {
.raw_crop_first_pixel_shift = 16,
.raw_crop_first_pixel_mask = 0xFFFF,
.raw_crop_last_pixel_shift = 0x0,
@@ -80,35 +81,57 @@ static struct cam_vfe_camif_reg_data vfe_170_camif_reg_data = {
.reg_update_irq_mask = 0x00000010,
.eof_irq_mask = 0x00000002,
.error_irq_mask0 = 0x0003FC00,
- .error_irq_mask1 = 0x0FFF7E80,
+ .error_irq_mask1 = 0xEFFF7E80,
.enable_diagnostic_hw = 0x1,
};
-struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_170_reg = {
+static struct cam_vfe_camif_lite_ver2_reg vfe175_camif_lite_reg = {
+ .camif_lite_cmd = 0x00000FC0,
+ .camif_lite_config = 0x00000FC4,
+ .lite_skip_period = 0x00000FC8,
+ .lite_irq_subsample_pattern = 0x00000FCC,
+ .lite_epoch_irq = 0x00000FD0,
+ .reg_update_cmd = 0x000004AC,
+};
+
+static struct cam_vfe_camif_lite_ver2_reg_data vfe175_camif_lite_reg_data = {
+ .dual_pd_reg_update_cmd_data = 0x20,
+ .lite_epoch_line_cfg = 0x00140014,
+ .lite_sof_irq_mask = 0x00040000,
+ .lite_epoch0_irq_mask = 0x00100000,
+ .dual_pd_reg_upd_irq_mask = 0x04000000,
+ .lite_eof_irq_mask = 0x00080000,
+ .lite_error_irq_mask0 = 0x00400000,
+ .lite_error_irq_mask1 = 0x00004100,
+ .extern_reg_update_shift = 4,
+ .dual_pd_path_sel_shift = 24,
+};
+
+struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_175_reg = {
.reset = 0x0000001C,
.cgc_ovd = 0x0000002C,
.enable = 0x00000040,
};
-struct cam_vfe_top_ver2_reg_offset_module_ctrl stats_170_reg = {
+struct cam_vfe_top_ver2_reg_offset_module_ctrl stats_175_reg = {
.reset = 0x00000020,
.cgc_ovd = 0x00000030,
.enable = 0x00000044,
};
-struct cam_vfe_top_ver2_reg_offset_module_ctrl color_170_reg = {
+struct cam_vfe_top_ver2_reg_offset_module_ctrl color_175_reg = {
.reset = 0x00000024,
.cgc_ovd = 0x00000034,
.enable = 0x00000048,
};
-struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_170_reg = {
+struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_175_reg = {
.reset = 0x00000028,
.cgc_ovd = 0x00000038,
.enable = 0x0000004C,
};
-static struct cam_vfe_top_ver2_reg_offset_common vfe170_top_common_reg = {
+static struct cam_vfe_top_ver2_reg_offset_common vfe175_top_common_reg = {
.hw_version = 0x00000000,
.hw_capability = 0x00000004,
.lens_feature = 0x00000008,
@@ -117,10 +140,10 @@ static struct cam_vfe_top_ver2_reg_offset_common vfe170_top_common_reg = {
.zoom_feature = 0x00000014,
.global_reset_cmd = 0x00000018,
.module_ctrl = {
- &lens_170_reg,
- &stats_170_reg,
- &color_170_reg,
- &zoom_170_reg,
+ &lens_175_reg,
+ &stats_175_reg,
+ &color_175_reg,
+ &zoom_175_reg,
},
.bus_cgc_ovd = 0x0000003C,
.core_cfg = 0x00000050,
@@ -129,42 +152,47 @@ static struct cam_vfe_top_ver2_reg_offset_common vfe170_top_common_reg = {
.reg_update_cmd = 0x000004AC,
};
-static struct cam_vfe_rdi_ver2_reg vfe170_rdi_reg = {
+static struct cam_vfe_rdi_ver2_reg vfe175_rdi_reg = {
.reg_update_cmd = 0x000004AC,
};
-static struct cam_vfe_rdi_reg_data vfe_170_rdi_0_data = {
+static struct cam_vfe_rdi_reg_data vfe_175_rdi_0_data = {
.reg_update_cmd_data = 0x2,
.sof_irq_mask = 0x8000000,
.reg_update_irq_mask = 0x20,
};
-static struct cam_vfe_rdi_reg_data vfe_170_rdi_1_data = {
+static struct cam_vfe_rdi_reg_data vfe_175_rdi_1_data = {
.reg_update_cmd_data = 0x4,
.sof_irq_mask = 0x10000000,
.reg_update_irq_mask = 0x40,
};
-static struct cam_vfe_rdi_reg_data vfe_170_rdi_2_data = {
+static struct cam_vfe_rdi_reg_data vfe_175_rdi_2_data = {
.reg_update_cmd_data = 0x8,
.sof_irq_mask = 0x20000000,
.reg_update_irq_mask = 0x80,
};
-static struct cam_vfe_top_ver2_hw_info vfe170_top_hw_info = {
- .common_reg = &vfe170_top_common_reg,
+static struct cam_vfe_top_ver2_hw_info vfe175_top_hw_info = {
+ .common_reg = &vfe175_top_common_reg,
.camif_hw_info = {
- .common_reg = &vfe170_top_common_reg,
- .camif_reg = &vfe170_camif_reg,
- .reg_data = &vfe_170_camif_reg_data,
+ .common_reg = &vfe175_top_common_reg,
+ .camif_reg = &vfe175_camif_reg,
+ .reg_data = &vfe_175_camif_reg_data,
+ },
+ .camif_lite_hw_info = {
+ .common_reg = &vfe175_top_common_reg,
+ .camif_lite_reg = &vfe175_camif_lite_reg,
+ .reg_data = &vfe175_camif_lite_reg_data,
},
.rdi_hw_info = {
- .common_reg = &vfe170_top_common_reg,
- .rdi_reg = &vfe170_rdi_reg,
+ .common_reg = &vfe175_top_common_reg,
+ .rdi_reg = &vfe175_rdi_reg,
.reg_data = {
- &vfe_170_rdi_0_data,
- &vfe_170_rdi_1_data,
- &vfe_170_rdi_2_data,
+ &vfe_175_rdi_0_data,
+ &vfe_175_rdi_1_data,
+ &vfe_175_rdi_2_data,
NULL,
},
},
@@ -173,10 +201,11 @@ static struct cam_vfe_top_ver2_hw_info vfe170_top_hw_info = {
CAM_VFE_RDI_VER_1_0,
CAM_VFE_RDI_VER_1_0,
CAM_VFE_RDI_VER_1_0,
+ CAM_VFE_CAMIF_LITE_VER_2_0,
},
};
-static struct cam_irq_register_set vfe170_bus_irq_reg[3] = {
+static struct cam_irq_register_set vfe175_bus_irq_reg[3] = {
{
.mask_reg_offset = 0x00002044,
.clear_reg_offset = 0x00002050,
@@ -194,29 +223,59 @@ static struct cam_irq_register_set vfe170_bus_irq_reg[3] = {
},
};
-static struct cam_vfe_bus_ver2_reg_offset_ubwc_client ubwc_regs_client_3 = {
+static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
+ vfe175_ubwc_regs_client_3 = {
.tile_cfg = 0x0000252C,
.h_init = 0x00002530,
.v_init = 0x00002534,
.meta_addr = 0x00002538,
.meta_offset = 0x0000253C,
.meta_stride = 0x00002540,
- .mode_cfg = 0x00002544,
+ .mode_cfg_0 = 0x00002544,
+ .mode_cfg_1 = 0x000025A4,
.bw_limit = 0x000025A0,
};
-static struct cam_vfe_bus_ver2_reg_offset_ubwc_client ubwc_regs_client_4 = {
+static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
+ vfe175_ubwc_regs_client_4 = {
.tile_cfg = 0x0000262C,
.h_init = 0x00002630,
.v_init = 0x00002634,
.meta_addr = 0x00002638,
.meta_offset = 0x0000263C,
.meta_stride = 0x00002640,
- .mode_cfg = 0x00002644,
+ .mode_cfg_0 = 0x00002644,
+ .mode_cfg_1 = 0x000026A4,
.bw_limit = 0x000026A0,
};
-static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
+static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
+ vfe175_ubwc_regs_client_20 = {
+ .tile_cfg = 0x0000362C,
+ .h_init = 0x00003630,
+ .v_init = 0x00003634,
+ .meta_addr = 0x00003638,
+ .meta_offset = 0x0000363C,
+ .meta_stride = 0x00003640,
+ .mode_cfg_0 = 0x00003644,
+ .mode_cfg_1 = 0x000036A4,
+ .bw_limit = 0x000036A0,
+};
+
+static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
+ vfe175_ubwc_regs_client_21 = {
+ .tile_cfg = 0x0000372C,
+ .h_init = 0x00003730,
+ .v_init = 0x00003734,
+ .meta_addr = 0x00003738,
+ .meta_offset = 0x0000373C,
+ .meta_stride = 0x00003740,
+ .mode_cfg_0 = 0x00003744,
+ .mode_cfg_1 = 0x000037A4,
+ .bw_limit = 0x000037A0,
+};
+
+static struct cam_vfe_bus_ver2_hw_info vfe175_bus_hw_info = {
.common_reg = {
.hw_version = 0x00002000,
.hw_capability = 0x00002004,
@@ -226,7 +285,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
.dual_master_comp_cfg = 0x00002028,
.irq_reg_info = {
.num_registers = 3,
- .irq_reg_set = vfe170_bus_irq_reg,
+ .irq_reg_set = vfe175_bus_irq_reg,
.global_clear_offset = 0x00002068,
.global_clear_bitmask = 0x00000001,
},
@@ -240,7 +299,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
.debug_status_cfg = 0x0000226C,
.debug_status_0 = 0x00002270,
},
- .num_client = 20,
+ .num_client = 24,
.bus_client_reg = {
/* BUS Client 0 */
{
@@ -324,7 +383,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
.framedrop_pattern = 0x00002554,
.frame_inc = 0x00002558,
.burst_limit = 0x0000255C,
- .ubwc_regs = &ubwc_regs_client_3,
+ .ubwc_regs = &vfe175_ubwc_regs_client_3,
},
/* BUS Client 4 */
{
@@ -345,7 +404,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
.framedrop_pattern = 0x00002654,
.frame_inc = 0x00002658,
.burst_limit = 0x0000265C,
- .ubwc_regs = &ubwc_regs_client_4,
+ .ubwc_regs = &vfe175_ubwc_regs_client_4,
},
/* BUS Client 5 */
{
@@ -662,6 +721,90 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
.burst_limit = 0x0000355C,
.ubwc_regs = NULL,
},
+ /* BUS Client 20 */
+ {
+ .status0 = 0x00003600,
+ .status1 = 0x00003604,
+ .cfg = 0x00003608,
+ .header_addr = 0x0000360C,
+ .header_cfg = 0x00003610,
+ .image_addr = 0x00003614,
+ .image_addr_offset = 0x00003618,
+ .buffer_width_cfg = 0x0000361C,
+ .buffer_height_cfg = 0x00003620,
+ .packer_cfg = 0x00003624,
+ .stride = 0x00003628,
+ .irq_subsample_period = 0x00003648,
+ .irq_subsample_pattern = 0x0000364C,
+ .framedrop_period = 0x00003650,
+ .framedrop_pattern = 0x00003654,
+ .frame_inc = 0x00003658,
+ .burst_limit = 0x0000365C,
+ .ubwc_regs = &vfe175_ubwc_regs_client_20,
+ },
+ /* BUS Client 21 */
+ {
+ .status0 = 0x00003700,
+ .status1 = 0x00003704,
+ .cfg = 0x00003708,
+ .header_addr = 0x0000370C,
+ .header_cfg = 0x00003710,
+ .image_addr = 0x00003714,
+ .image_addr_offset = 0x00003718,
+ .buffer_width_cfg = 0x0000371C,
+ .buffer_height_cfg = 0x00003720,
+ .packer_cfg = 0x00003724,
+ .stride = 0x00003728,
+ .irq_subsample_period = 0x00003748,
+ .irq_subsample_pattern = 0x0000374C,
+ .framedrop_period = 0x00003750,
+ .framedrop_pattern = 0x00003754,
+ .frame_inc = 0x00003758,
+ .burst_limit = 0x0000375C,
+ .ubwc_regs = &vfe175_ubwc_regs_client_21,
+ },
+ /* BUS Client 22 */
+ {
+ .status0 = 0x00003800,
+ .status1 = 0x00003804,
+ .cfg = 0x00003808,
+ .header_addr = 0x0000380C,
+ .header_cfg = 0x00003810,
+ .image_addr = 0x00003814,
+ .image_addr_offset = 0x00003818,
+ .buffer_width_cfg = 0x0000381C,
+ .buffer_height_cfg = 0x00003820,
+ .packer_cfg = 0x00003824,
+ .stride = 0x00003828,
+ .irq_subsample_period = 0x00003848,
+ .irq_subsample_pattern = 0x0000384C,
+ .framedrop_period = 0x00003850,
+ .framedrop_pattern = 0x00003854,
+ .frame_inc = 0x00003858,
+ .burst_limit = 0x0000385C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 23 */
+ {
+ .status0 = 0x00003900,
+ .status1 = 0x00003904,
+ .cfg = 0x00003908,
+ .header_addr = 0x0000390C,
+ .header_cfg = 0x00003910,
+ .image_addr = 0x00003914,
+ .image_addr_offset = 0x00003918,
+ .buffer_width_cfg = 0x0000391C,
+ .buffer_height_cfg = 0x00003920,
+ .packer_cfg = 0x00003924,
+ .stride = 0x00003928,
+ .irq_subsample_period = 0x00003948,
+ .irq_subsample_pattern = 0x0000394C,
+ .framedrop_period = 0x00003950,
+ .framedrop_pattern = 0x00003954,
+ .frame_inc = 0x00003958,
+ .burst_limit = 0x0000395C,
+ .ubwc_regs = NULL,
+ },
},
.comp_grp_reg = {
/* CAM_VFE_BUS_VER2_COMP_GRP_0 */
@@ -721,7 +864,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
.addr_sync_mask = 0x0000209C,
},
},
- .num_out = 18,
+ .num_out = 22,
.vfe_out_hw_info = {
{
.vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI0,
@@ -822,21 +965,44 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
.max_width = -1,
.max_height = -1,
},
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP,
+ .max_width = 4096,
+ .max_height = 4096,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS4_DISP,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS16_DISP,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_2PD,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
},
};
-struct cam_vfe_hw_info cam_vfe170_hw_info = {
- .irq_reg_info = &vfe170_top_irq_reg_info,
+struct cam_vfe_hw_info cam_vfe175_hw_info = {
+ .irq_reg_info = &vfe175_top_irq_reg_info,
.bus_version = CAM_VFE_BUS_VER_2_0,
- .bus_hw_info = &vfe170_bus_hw_info,
+ .bus_hw_info = &vfe175_bus_hw_info,
.top_version = CAM_VFE_TOP_VER_2_0,
- .top_hw_info = &vfe170_top_hw_info,
+ .top_hw_info = &vfe175_top_hw_info,
.camif_version = CAM_VFE_CAMIF_VER_2_0,
- .camif_reg = &vfe170_camif_reg,
+ .camif_reg = &vfe175_camif_reg,
+
+ .camif_lite_version = CAM_VFE_CAMIF_LITE_VER_2_0,
+ .camif_lite_reg = &vfe175_camif_lite_reg,
};
-#endif /* _CAM_VFE170_H_ */
+#endif /* _CAM_VFE175_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h
new file mode 100644
index 000000000000..f966fe490db4
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h
@@ -0,0 +1,1117 @@
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CAM_VFE175_130_H_
+#define _CAM_VFE175_130_H_
+
+#include "cam_vfe_camif_ver2.h"
+#include "cam_vfe_camif_lite_ver2.h"
+#include "cam_vfe_bus_ver2.h"
+#include "cam_vfe_bus_rd_ver1.h"
+#include "cam_irq_controller.h"
+#include "cam_vfe_top_ver2.h"
+#include "cam_vfe_core.h"
+
+static struct cam_irq_register_set vfe175_130_top_irq_reg_set[2] = {
+ {
+ .mask_reg_offset = 0x0000005C,
+ .clear_reg_offset = 0x00000064,
+ .status_reg_offset = 0x0000006C,
+ },
+ {
+ .mask_reg_offset = 0x00000060,
+ .clear_reg_offset = 0x00000068,
+ .status_reg_offset = 0x00000070,
+ },
+};
+
+static struct cam_irq_controller_reg_info vfe175_130_top_irq_reg_info = {
+ .num_registers = 2,
+ .irq_reg_set = vfe175_130_top_irq_reg_set,
+ .global_clear_offset = 0x00000058,
+ .global_clear_bitmask = 0x00000001,
+};
+
+static struct cam_vfe_camif_ver2_reg vfe175_130_camif_reg = {
+ .camif_cmd = 0x00000478,
+ .camif_config = 0x0000047C,
+ .line_skip_pattern = 0x00000488,
+ .pixel_skip_pattern = 0x0000048C,
+ .skip_period = 0x00000490,
+ .irq_subsample_pattern = 0x0000049C,
+ .epoch_irq = 0x000004A0,
+ .raw_crop_width_cfg = 0x00000CE4,
+ .raw_crop_height_cfg = 0x00000CE8,
+ .reg_update_cmd = 0x000004AC,
+ .vfe_diag_config = 0x00000C48,
+ .vfe_diag_sensor_status = 0x00000C4C,
+};
+
+static struct cam_vfe_camif_reg_data vfe_175_130_camif_reg_data = {
+ .raw_crop_first_pixel_shift = 16,
+ .raw_crop_first_pixel_mask = 0xFFFF,
+ .raw_crop_last_pixel_shift = 0x0,
+ .raw_crop_last_pixel_mask = 0x3FFF,
+ .raw_crop_first_line_shift = 16,
+ .raw_crop_first_line_mask = 0xFFFF,
+ .raw_crop_last_line_shift = 0,
+ .raw_crop_last_line_mask = 0x3FFF,
+ .input_mux_sel_shift = 5,
+ .input_mux_sel_mask = 0x3,
+ .extern_reg_update_shift = 4,
+ .extern_reg_update_mask = 1,
+ .pixel_pattern_shift = 0,
+ .pixel_pattern_mask = 0x7,
+ .dsp_mode_shift = 23,
+ .dsp_mode_mask = 0x1,
+ .dsp_en_shift = 3,
+ .dsp_en_mask = 0x1,
+ .reg_update_cmd_data = 0x1,
+ .epoch_line_cfg = 0x00140014,
+ .sof_irq_mask = 0x00000001,
+ .epoch0_irq_mask = 0x00000004,
+ .reg_update_irq_mask = 0x00000010,
+ .eof_irq_mask = 0x00000002,
+ .error_irq_mask0 = 0x0003FC00,
+ .error_irq_mask1 = 0xEFFF7E80,
+ .enable_diagnostic_hw = 0x1,
+};
+
+static struct cam_vfe_fe_ver1_reg vfe175_130_fe_reg = {
+ .camif_cmd = 0x00000478,
+ .camif_config = 0x0000047C,
+ .line_skip_pattern = 0x00000488,
+ .pixel_skip_pattern = 0x0000048C,
+ .skip_period = 0x00000490,
+ .irq_subsample_pattern = 0x0000049C,
+ .epoch_irq = 0x000004A0,
+ .raw_crop_width_cfg = 0x00000CE4,
+ .raw_crop_height_cfg = 0x00000CE8,
+ .reg_update_cmd = 0x000004AC,
+ .vfe_diag_config = 0x00000C48,
+ .vfe_diag_sensor_status = 0x00000C4C,
+ .fe_cfg = 0x00000084,
+};
+
+static struct cam_vfe_fe_reg_data vfe_175_130_fe_reg_data = {
+ .raw_crop_first_pixel_shift = 16,
+ .raw_crop_first_pixel_mask = 0xFFFF,
+ .raw_crop_last_pixel_shift = 0x0,
+ .raw_crop_last_pixel_mask = 0x3FFF,
+ .raw_crop_first_line_shift = 16,
+ .raw_crop_first_line_mask = 0xFFFF,
+ .raw_crop_last_line_shift = 0,
+ .raw_crop_last_line_mask = 0x3FFF,
+ .input_mux_sel_shift = 5,
+ .input_mux_sel_mask = 0x3,
+ .extern_reg_update_shift = 4,
+ .extern_reg_update_mask = 1,
+ .pixel_pattern_shift = 0,
+ .pixel_pattern_mask = 0x7,
+ .dsp_mode_shift = 23,
+ .dsp_mode_mask = 0x1,
+ .dsp_en_shift = 3,
+ .dsp_en_mask = 0x1,
+ .reg_update_cmd_data = 0x1,
+ .epoch_line_cfg = 0x00140014,
+ .sof_irq_mask = 0x00000001,
+ .epoch0_irq_mask = 0x00000004,
+ .reg_update_irq_mask = 0x00000010,
+ .eof_irq_mask = 0x00000002,
+ .error_irq_mask0 = 0x0003FC00,
+ .error_irq_mask1 = 0xEFFF7E80,
+ .enable_diagnostic_hw = 0x1,
+ .fe_mux_data = 0x2,
+ .hbi_cnt_shift = 0x8,
+};
+
+static struct cam_vfe_camif_lite_ver2_reg vfe175_130_camif_lite_reg = {
+ .camif_lite_cmd = 0x00000FC0,
+ .camif_lite_config = 0x00000FC4,
+ .lite_skip_period = 0x00000FC8,
+ .lite_irq_subsample_pattern = 0x00000FCC,
+ .lite_epoch_irq = 0x00000FD0,
+ .reg_update_cmd = 0x000004AC,
+};
+
+static struct cam_vfe_camif_lite_ver2_reg_data
+ vfe175_130_camif_lite_reg_data = {
+ .dual_pd_reg_update_cmd_data = 0x20,
+ .lite_epoch_line_cfg = 0x00140014,
+ .lite_sof_irq_mask = 0x00040000,
+ .lite_epoch0_irq_mask = 0x00100000,
+ .dual_pd_reg_upd_irq_mask = 0x04000000,
+ .lite_eof_irq_mask = 0x00080000,
+ .lite_error_irq_mask0 = 0x00400000,
+ .lite_error_irq_mask1 = 0x00004100,
+ .extern_reg_update_shift = 4,
+ .dual_pd_path_sel_shift = 24,
+};
+
+struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_175_130_reg = {
+ .reset = 0x0000001C,
+ .cgc_ovd = 0x0000002C,
+ .enable = 0x00000040,
+};
+
+struct cam_vfe_top_ver2_reg_offset_module_ctrl stats_175_130_reg = {
+ .reset = 0x00000020,
+ .cgc_ovd = 0x00000030,
+ .enable = 0x00000044,
+};
+
+struct cam_vfe_top_ver2_reg_offset_module_ctrl color_175_130_reg = {
+ .reset = 0x00000024,
+ .cgc_ovd = 0x00000034,
+ .enable = 0x00000048,
+};
+
+struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_175_130_reg = {
+ .reset = 0x00000028,
+ .cgc_ovd = 0x00000038,
+ .enable = 0x0000004C,
+};
+
+static struct cam_vfe_top_ver2_reg_offset_common vfe175_130_top_common_reg = {
+ .hw_version = 0x00000000,
+ .hw_capability = 0x00000004,
+ .lens_feature = 0x00000008,
+ .stats_feature = 0x0000000C,
+ .color_feature = 0x00000010,
+ .zoom_feature = 0x00000014,
+ .global_reset_cmd = 0x00000018,
+ .module_ctrl = {
+ &lens_175_130_reg,
+ &stats_175_130_reg,
+ &color_175_130_reg,
+ &zoom_175_130_reg,
+ },
+ .bus_cgc_ovd = 0x0000003C,
+ .core_cfg = 0x00000050,
+ .three_D_cfg = 0x00000054,
+ .violation_status = 0x0000007C,
+ .reg_update_cmd = 0x000004AC,
+};
+
+static struct cam_vfe_rdi_ver2_reg vfe175_130_rdi_reg = {
+ .reg_update_cmd = 0x000004AC,
+};
+
+static struct cam_vfe_rdi_reg_data vfe_175_130_rdi_0_data = {
+ .reg_update_cmd_data = 0x2,
+ .sof_irq_mask = 0x8000000,
+ .reg_update_irq_mask = 0x20,
+};
+
+static struct cam_vfe_rdi_reg_data vfe_175_130_rdi_1_data = {
+ .reg_update_cmd_data = 0x4,
+ .sof_irq_mask = 0x10000000,
+ .reg_update_irq_mask = 0x40,
+};
+
+static struct cam_vfe_rdi_reg_data vfe_175_130_rdi_2_data = {
+ .reg_update_cmd_data = 0x8,
+ .sof_irq_mask = 0x20000000,
+ .reg_update_irq_mask = 0x80,
+};
+
+static struct cam_vfe_top_ver2_hw_info vfe175_130_top_hw_info = {
+ .common_reg = &vfe175_130_top_common_reg,
+ .camif_hw_info = {
+ .common_reg = &vfe175_130_top_common_reg,
+ .camif_reg = &vfe175_130_camif_reg,
+ .reg_data = &vfe_175_130_camif_reg_data,
+ },
+ .camif_lite_hw_info = {
+ .common_reg = &vfe175_130_top_common_reg,
+ .camif_lite_reg = &vfe175_130_camif_lite_reg,
+ .reg_data = &vfe175_130_camif_lite_reg_data,
+ },
+ .rdi_hw_info = {
+ .common_reg = &vfe175_130_top_common_reg,
+ .rdi_reg = &vfe175_130_rdi_reg,
+ .reg_data = {
+ &vfe_175_130_rdi_0_data,
+ &vfe_175_130_rdi_1_data,
+ &vfe_175_130_rdi_2_data,
+ NULL,
+ },
+ },
+ .fe_hw_info = {
+ .common_reg = &vfe175_130_top_common_reg,
+ .fe_reg = &vfe175_130_fe_reg,
+ .reg_data = &vfe_175_130_fe_reg_data,
+ },
+ .mux_type = {
+ CAM_VFE_CAMIF_VER_2_0,
+ CAM_VFE_RDI_VER_1_0,
+ CAM_VFE_RDI_VER_1_0,
+ CAM_VFE_RDI_VER_1_0,
+ CAM_VFE_CAMIF_LITE_VER_2_0,
+ CAM_VFE_IN_RD_VER_1_0,
+ },
+};
+
+static struct cam_irq_register_set vfe175_130_bus_rd_irq_reg[1] = {
+ {
+ .mask_reg_offset = 0x00005010,
+ .clear_reg_offset = 0x00005014,
+ .status_reg_offset = 0x0000501C,
+ },
+};
+
+static struct cam_irq_register_set vfe175_130_bus_irq_reg[3] = {
+ {
+ .mask_reg_offset = 0x00002044,
+ .clear_reg_offset = 0x00002050,
+ .status_reg_offset = 0x0000205C,
+ },
+ {
+ .mask_reg_offset = 0x00002048,
+ .clear_reg_offset = 0x00002054,
+ .status_reg_offset = 0x00002060,
+ },
+ {
+ .mask_reg_offset = 0x0000204C,
+ .clear_reg_offset = 0x00002058,
+ .status_reg_offset = 0x00002064,
+ },
+};
+
+static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
+ vfe175_130_ubwc_regs_client_3 = {
+ .tile_cfg = 0x0000252C,
+ .h_init = 0x00002530,
+ .v_init = 0x00002534,
+ .meta_addr = 0x00002538,
+ .meta_offset = 0x0000253C,
+ .meta_stride = 0x00002540,
+ .mode_cfg_0 = 0x00002544,
+ .mode_cfg_1 = 0x000025A4,
+ .bw_limit = 0x000025A0,
+};
+
+static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
+ vfe175_130_ubwc_regs_client_4 = {
+ .tile_cfg = 0x0000262C,
+ .h_init = 0x00002630,
+ .v_init = 0x00002634,
+ .meta_addr = 0x00002638,
+ .meta_offset = 0x0000263C,
+ .meta_stride = 0x00002640,
+ .mode_cfg_0 = 0x00002644,
+ .mode_cfg_1 = 0x000026A4,
+ .bw_limit = 0x000026A0,
+};
+
+static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
+ vfe175_130_ubwc_regs_client_20 = {
+ .tile_cfg = 0x0000362C,
+ .h_init = 0x00003630,
+ .v_init = 0x00003634,
+ .meta_addr = 0x00003638,
+ .meta_offset = 0x0000363C,
+ .meta_stride = 0x00003640,
+ .mode_cfg_0 = 0x00003644,
+ .mode_cfg_1 = 0x000036A4,
+ .bw_limit = 0x000036A0,
+};
+
+static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
+ vfe175_130_ubwc_regs_client_21 = {
+ .tile_cfg = 0x0000372C,
+ .h_init = 0x00003730,
+ .v_init = 0x00003734,
+ .meta_addr = 0x00003738,
+ .meta_offset = 0x0000373C,
+ .meta_stride = 0x00003740,
+ .mode_cfg_0 = 0x00003744,
+ .mode_cfg_1 = 0x000037A4,
+ .bw_limit = 0x000037A0,
+};
+
+static struct cam_vfe_bus_rd_ver1_hw_info vfe175_130_bus_rd_hw_info = {
+ .common_reg = {
+ .hw_version = 0x00005000,
+ .hw_capability = 0x00005004,
+ .sw_reset = 0x00005008,
+ .cgc_ovd = 0x0000500C,
+ .pwr_iso_cfg = 0x000050CC,
+ .input_if_cmd = 0x00005020,
+ .test_bus_ctrl = 0x00005048,
+ .irq_reg_info = {
+ .num_registers = 1,
+ .irq_reg_set = vfe175_130_bus_rd_irq_reg,
+ .global_clear_offset = 0x00005018,
+ .global_clear_bitmask = 0x00000001,
+ },
+ },
+ .num_client = 1,
+ .bus_client_reg = {
+ /* BUS Client 0 */
+ {
+ .cfg = 0x00005050,
+ .image_addr = 0x00005058,
+ .buffer_width_cfg = 0x0000505C,
+ .unpacker_cfg = 0x00005064,
+ .stride = 0x00005060,
+ .burst_limit = 0x00005080,
+ .latency_buf_allocation = 0x00005078,
+ .ubwc_regs = NULL,
+ },
+ },
+ .num_bus_rd_resc = 1,
+ .vfe_bus_rd_hw_info = {
+ {
+ .vfe_bus_rd_type = CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ },
+};
+
+static struct cam_vfe_bus_ver2_hw_info vfe175_130_bus_hw_info = {
+ .common_reg = {
+ .hw_version = 0x00002000,
+ .hw_capability = 0x00002004,
+ .sw_reset = 0x00002008,
+ .cgc_ovd = 0x0000200C,
+ .pwr_iso_cfg = 0x000020CC,
+ .dual_master_comp_cfg = 0x00002028,
+ .irq_reg_info = {
+ .num_registers = 3,
+ .irq_reg_set = vfe175_130_bus_irq_reg,
+ .global_clear_offset = 0x00002068,
+ .global_clear_bitmask = 0x00000001,
+ },
+ .comp_error_status = 0x0000206C,
+ .comp_ovrwr_status = 0x00002070,
+ .dual_comp_error_status = 0x00002074,
+ .dual_comp_ovrwr_status = 0x00002078,
+ .addr_sync_cfg = 0x0000207C,
+ .addr_sync_frame_hdr = 0x00002080,
+ .addr_sync_no_sync = 0x00002084,
+ },
+ .num_client = 24,
+ .bus_client_reg = {
+ /* BUS Client 0 */
+ {
+ .status0 = 0x00002200,
+ .status1 = 0x00002204,
+ .cfg = 0x00002208,
+ .header_addr = 0x0000220C,
+ .header_cfg = 0x00002210,
+ .image_addr = 0x00002214,
+ .image_addr_offset = 0x00002218,
+ .buffer_width_cfg = 0x0000221C,
+ .buffer_height_cfg = 0x00002220,
+ .packer_cfg = 0x00002224,
+ .stride = 0x00002228,
+ .irq_subsample_period = 0x00002248,
+ .irq_subsample_pattern = 0x0000224C,
+ .framedrop_period = 0x00002250,
+ .framedrop_pattern = 0x00002254,
+ .frame_inc = 0x00002258,
+ .burst_limit = 0x0000225C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 1 */
+ {
+ .status0 = 0x00002300,
+ .status1 = 0x00002304,
+ .cfg = 0x00002308,
+ .header_addr = 0x0000230C,
+ .header_cfg = 0x00002310,
+ .image_addr = 0x00002314,
+ .image_addr_offset = 0x00002318,
+ .buffer_width_cfg = 0x0000231C,
+ .buffer_height_cfg = 0x00002320,
+ .packer_cfg = 0x00002324,
+ .stride = 0x00002328,
+ .irq_subsample_period = 0x00002348,
+ .irq_subsample_pattern = 0x0000234C,
+ .framedrop_period = 0x00002350,
+ .framedrop_pattern = 0x00002354,
+ .frame_inc = 0x00002358,
+ .burst_limit = 0x0000235C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 2 */
+ {
+ .status0 = 0x00002400,
+ .status1 = 0x00002404,
+ .cfg = 0x00002408,
+ .header_addr = 0x0000240C,
+ .header_cfg = 0x00002410,
+ .image_addr = 0x00002414,
+ .image_addr_offset = 0x00002418,
+ .buffer_width_cfg = 0x0000241C,
+ .buffer_height_cfg = 0x00002420,
+ .packer_cfg = 0x00002424,
+ .stride = 0x00002428,
+ .irq_subsample_period = 0x00002448,
+ .irq_subsample_pattern = 0x0000244C,
+ .framedrop_period = 0x00002450,
+ .framedrop_pattern = 0x00002454,
+ .frame_inc = 0x00002458,
+ .burst_limit = 0x0000245C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 3 */
+ {
+ .status0 = 0x00002500,
+ .status1 = 0x00002504,
+ .cfg = 0x00002508,
+ .header_addr = 0x0000250C,
+ .header_cfg = 0x00002510,
+ .image_addr = 0x00002514,
+ .image_addr_offset = 0x00002518,
+ .buffer_width_cfg = 0x0000251C,
+ .buffer_height_cfg = 0x00002520,
+ .packer_cfg = 0x00002524,
+ .stride = 0x00002528,
+ .irq_subsample_period = 0x00002548,
+ .irq_subsample_pattern = 0x0000254C,
+ .framedrop_period = 0x00002550,
+ .framedrop_pattern = 0x00002554,
+ .frame_inc = 0x00002558,
+ .burst_limit = 0x0000255C,
+ .ubwc_regs =
+ &vfe175_130_ubwc_regs_client_3,
+ },
+ /* BUS Client 4 */
+ {
+ .status0 = 0x00002600,
+ .status1 = 0x00002604,
+ .cfg = 0x00002608,
+ .header_addr = 0x0000260C,
+ .header_cfg = 0x00002610,
+ .image_addr = 0x00002614,
+ .image_addr_offset = 0x00002618,
+ .buffer_width_cfg = 0x0000261C,
+ .buffer_height_cfg = 0x00002620,
+ .packer_cfg = 0x00002624,
+ .stride = 0x00002628,
+ .irq_subsample_period = 0x00002648,
+ .irq_subsample_pattern = 0x0000264C,
+ .framedrop_period = 0x00002650,
+ .framedrop_pattern = 0x00002654,
+ .frame_inc = 0x00002658,
+ .burst_limit = 0x0000265C,
+ .ubwc_regs =
+ &vfe175_130_ubwc_regs_client_4,
+ },
+ /* BUS Client 5 */
+ {
+ .status0 = 0x00002700,
+ .status1 = 0x00002704,
+ .cfg = 0x00002708,
+ .header_addr = 0x0000270C,
+ .header_cfg = 0x00002710,
+ .image_addr = 0x00002714,
+ .image_addr_offset = 0x00002718,
+ .buffer_width_cfg = 0x0000271C,
+ .buffer_height_cfg = 0x00002720,
+ .packer_cfg = 0x00002724,
+ .stride = 0x00002728,
+ .irq_subsample_period = 0x00002748,
+ .irq_subsample_pattern = 0x0000274C,
+ .framedrop_period = 0x00002750,
+ .framedrop_pattern = 0x00002754,
+ .frame_inc = 0x00002758,
+ .burst_limit = 0x0000275C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 6 */
+ {
+ .status0 = 0x00002800,
+ .status1 = 0x00002804,
+ .cfg = 0x00002808,
+ .header_addr = 0x0000280C,
+ .header_cfg = 0x00002810,
+ .image_addr = 0x00002814,
+ .image_addr_offset = 0x00002818,
+ .buffer_width_cfg = 0x0000281C,
+ .buffer_height_cfg = 0x00002820,
+ .packer_cfg = 0x00002824,
+ .stride = 0x00002828,
+ .irq_subsample_period = 0x00002848,
+ .irq_subsample_pattern = 0x0000284C,
+ .framedrop_period = 0x00002850,
+ .framedrop_pattern = 0x00002854,
+ .frame_inc = 0x00002858,
+ .burst_limit = 0x0000285C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 7 */
+ {
+ .status0 = 0x00002900,
+ .status1 = 0x00002904,
+ .cfg = 0x00002908,
+ .header_addr = 0x0000290C,
+ .header_cfg = 0x00002910,
+ .image_addr = 0x00002914,
+ .image_addr_offset = 0x00002918,
+ .buffer_width_cfg = 0x0000291C,
+ .buffer_height_cfg = 0x00002920,
+ .packer_cfg = 0x00002924,
+ .stride = 0x00002928,
+ .irq_subsample_period = 0x00002948,
+ .irq_subsample_pattern = 0x0000294C,
+ .framedrop_period = 0x00002950,
+ .framedrop_pattern = 0x00002954,
+ .frame_inc = 0x00002958,
+ .burst_limit = 0x0000295C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 8 */
+ {
+ .status0 = 0x00002A00,
+ .status1 = 0x00002A04,
+ .cfg = 0x00002A08,
+ .header_addr = 0x00002A0C,
+ .header_cfg = 0x00002A10,
+ .image_addr = 0x00002A14,
+ .image_addr_offset = 0x00002A18,
+ .buffer_width_cfg = 0x00002A1C,
+ .buffer_height_cfg = 0x00002A20,
+ .packer_cfg = 0x00002A24,
+ .stride = 0x00002A28,
+ .irq_subsample_period = 0x00002A48,
+ .irq_subsample_pattern = 0x00002A4C,
+ .framedrop_period = 0x00002A50,
+ .framedrop_pattern = 0x00002A54,
+ .frame_inc = 0x00002A58,
+ .burst_limit = 0x00002A5C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 9 */
+ {
+ .status0 = 0x00002B00,
+ .status1 = 0x00002B04,
+ .cfg = 0x00002B08,
+ .header_addr = 0x00002B0C,
+ .header_cfg = 0x00002B10,
+ .image_addr = 0x00002B14,
+ .image_addr_offset = 0x00002B18,
+ .buffer_width_cfg = 0x00002B1C,
+ .buffer_height_cfg = 0x00002B20,
+ .packer_cfg = 0x00002B24,
+ .stride = 0x00002B28,
+ .irq_subsample_period = 0x00002B48,
+ .irq_subsample_pattern = 0x00002B4C,
+ .framedrop_period = 0x00002B50,
+ .framedrop_pattern = 0x00002B54,
+ .frame_inc = 0x00002B58,
+ .burst_limit = 0x00002B5C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 10 */
+ {
+ .status0 = 0x00002C00,
+ .status1 = 0x00002C04,
+ .cfg = 0x00002C08,
+ .header_addr = 0x00002C0C,
+ .header_cfg = 0x00002C10,
+ .image_addr = 0x00002C14,
+ .image_addr_offset = 0x00002C18,
+ .buffer_width_cfg = 0x00002C1C,
+ .buffer_height_cfg = 0x00002C20,
+ .packer_cfg = 0x00002C24,
+ .stride = 0x00002C28,
+ .irq_subsample_period = 0x00002C48,
+ .irq_subsample_pattern = 0x00002C4C,
+ .framedrop_period = 0x00002C50,
+ .framedrop_pattern = 0x00002C54,
+ .frame_inc = 0x00002C58,
+ .burst_limit = 0x00002C5C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 11 */
+ {
+ .status0 = 0x00002D00,
+ .status1 = 0x00002D04,
+ .cfg = 0x00002D08,
+ .header_addr = 0x00002D0C,
+ .header_cfg = 0x00002D10,
+ .image_addr = 0x00002D14,
+ .image_addr_offset = 0x00002D18,
+ .buffer_width_cfg = 0x00002D1C,
+ .buffer_height_cfg = 0x00002D20,
+ .packer_cfg = 0x00002D24,
+ .stride = 0x00002D28,
+ .irq_subsample_period = 0x00002D48,
+ .irq_subsample_pattern = 0x00002D4C,
+ .framedrop_period = 0x00002D50,
+ .framedrop_pattern = 0x00002D54,
+ .frame_inc = 0x00002D58,
+ .burst_limit = 0x00002D5C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 12 */
+ {
+ .status0 = 0x00002E00,
+ .status1 = 0x00002E04,
+ .cfg = 0x00002E08,
+ .header_addr = 0x00002E0C,
+ .header_cfg = 0x00002E10,
+ .image_addr = 0x00002E14,
+ .image_addr_offset = 0x00002E18,
+ .buffer_width_cfg = 0x00002E1C,
+ .buffer_height_cfg = 0x00002E20,
+ .packer_cfg = 0x00002E24,
+ .stride = 0x00002E28,
+ .irq_subsample_period = 0x00002E48,
+ .irq_subsample_pattern = 0x00002E4C,
+ .framedrop_period = 0x00002E50,
+ .framedrop_pattern = 0x00002E54,
+ .frame_inc = 0x00002E58,
+ .burst_limit = 0x00002E5C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 13 */
+ {
+ .status0 = 0x00002F00,
+ .status1 = 0x00002F04,
+ .cfg = 0x00002F08,
+ .header_addr = 0x00002F0C,
+ .header_cfg = 0x00002F10,
+ .image_addr = 0x00002F14,
+ .image_addr_offset = 0x00002F18,
+ .buffer_width_cfg = 0x00002F1C,
+ .buffer_height_cfg = 0x00002F20,
+ .packer_cfg = 0x00002F24,
+ .stride = 0x00002F28,
+ .irq_subsample_period = 0x00002F48,
+ .irq_subsample_pattern = 0x00002F4C,
+ .framedrop_period = 0x00002F50,
+ .framedrop_pattern = 0x00002F54,
+ .frame_inc = 0x00002F58,
+ .burst_limit = 0x00002F5C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 14 */
+ {
+ .status0 = 0x00003000,
+ .status1 = 0x00003004,
+ .cfg = 0x00003008,
+ .header_addr = 0x0000300C,
+ .header_cfg = 0x00003010,
+ .image_addr = 0x00003014,
+ .image_addr_offset = 0x00003018,
+ .buffer_width_cfg = 0x0000301C,
+ .buffer_height_cfg = 0x00003020,
+ .packer_cfg = 0x00003024,
+ .stride = 0x00003028,
+ .irq_subsample_period = 0x00003048,
+ .irq_subsample_pattern = 0x0000304C,
+ .framedrop_period = 0x00003050,
+ .framedrop_pattern = 0x00003054,
+ .frame_inc = 0x00003058,
+ .burst_limit = 0x0000305C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 15 */
+ {
+ .status0 = 0x00003100,
+ .status1 = 0x00003104,
+ .cfg = 0x00003108,
+ .header_addr = 0x0000310C,
+ .header_cfg = 0x00003110,
+ .image_addr = 0x00003114,
+ .image_addr_offset = 0x00003118,
+ .buffer_width_cfg = 0x0000311C,
+ .buffer_height_cfg = 0x00003120,
+ .packer_cfg = 0x00003124,
+ .stride = 0x00003128,
+ .irq_subsample_period = 0x00003148,
+ .irq_subsample_pattern = 0x0000314C,
+ .framedrop_period = 0x00003150,
+ .framedrop_pattern = 0x00003154,
+ .frame_inc = 0x00003158,
+ .burst_limit = 0x0000315C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 16 */
+ {
+ .status0 = 0x00003200,
+ .status1 = 0x00003204,
+ .cfg = 0x00003208,
+ .header_addr = 0x0000320C,
+ .header_cfg = 0x00003210,
+ .image_addr = 0x00003214,
+ .image_addr_offset = 0x00003218,
+ .buffer_width_cfg = 0x0000321C,
+ .buffer_height_cfg = 0x00003220,
+ .packer_cfg = 0x00003224,
+ .stride = 0x00003228,
+ .irq_subsample_period = 0x00003248,
+ .irq_subsample_pattern = 0x0000324C,
+ .framedrop_period = 0x00003250,
+ .framedrop_pattern = 0x00003254,
+ .frame_inc = 0x00003258,
+ .burst_limit = 0x0000325C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 17 */
+ {
+ .status0 = 0x00003300,
+ .status1 = 0x00003304,
+ .cfg = 0x00003308,
+ .header_addr = 0x0000330C,
+ .header_cfg = 0x00003310,
+ .image_addr = 0x00003314,
+ .image_addr_offset = 0x00003318,
+ .buffer_width_cfg = 0x0000331C,
+ .buffer_height_cfg = 0x00003320,
+ .packer_cfg = 0x00003324,
+ .stride = 0x00003328,
+ .irq_subsample_period = 0x00003348,
+ .irq_subsample_pattern = 0x0000334C,
+ .framedrop_period = 0x00003350,
+ .framedrop_pattern = 0x00003354,
+ .frame_inc = 0x00003358,
+ .burst_limit = 0x0000335C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 18 */
+ {
+ .status0 = 0x00003400,
+ .status1 = 0x00003404,
+ .cfg = 0x00003408,
+ .header_addr = 0x0000340C,
+ .header_cfg = 0x00003410,
+ .image_addr = 0x00003414,
+ .image_addr_offset = 0x00003418,
+ .buffer_width_cfg = 0x0000341C,
+ .buffer_height_cfg = 0x00003420,
+ .packer_cfg = 0x00003424,
+ .stride = 0x00003428,
+ .irq_subsample_period = 0x00003448,
+ .irq_subsample_pattern = 0x0000344C,
+ .framedrop_period = 0x00003450,
+ .framedrop_pattern = 0x00003454,
+ .frame_inc = 0x00003458,
+ .burst_limit = 0x0000345C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 19 */
+ {
+ .status0 = 0x00003500,
+ .status1 = 0x00003504,
+ .cfg = 0x00003508,
+ .header_addr = 0x0000350C,
+ .header_cfg = 0x00003510,
+ .image_addr = 0x00003514,
+ .image_addr_offset = 0x00003518,
+ .buffer_width_cfg = 0x0000351C,
+ .buffer_height_cfg = 0x00003520,
+ .packer_cfg = 0x00003524,
+ .stride = 0x00003528,
+ .irq_subsample_period = 0x00003548,
+ .irq_subsample_pattern = 0x0000354C,
+ .framedrop_period = 0x00003550,
+ .framedrop_pattern = 0x00003554,
+ .frame_inc = 0x00003558,
+ .burst_limit = 0x0000355C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 20 */
+ {
+ .status0 = 0x00003600,
+ .status1 = 0x00003604,
+ .cfg = 0x00003608,
+ .header_addr = 0x0000360C,
+ .header_cfg = 0x00003610,
+ .image_addr = 0x00003614,
+ .image_addr_offset = 0x00003618,
+ .buffer_width_cfg = 0x0000361C,
+ .buffer_height_cfg = 0x00003620,
+ .packer_cfg = 0x00003624,
+ .stride = 0x00003628,
+ .irq_subsample_period = 0x00003648,
+ .irq_subsample_pattern = 0x0000364C,
+ .framedrop_period = 0x00003650,
+ .framedrop_pattern = 0x00003654,
+ .frame_inc = 0x00003658,
+ .burst_limit = 0x0000365C,
+ .ubwc_regs =
+ &vfe175_130_ubwc_regs_client_20,
+ },
+ /* BUS Client 21 */
+ {
+ .status0 = 0x00003700,
+ .status1 = 0x00003704,
+ .cfg = 0x00003708,
+ .header_addr = 0x0000370C,
+ .header_cfg = 0x00003710,
+ .image_addr = 0x00003714,
+ .image_addr_offset = 0x00003718,
+ .buffer_width_cfg = 0x0000371C,
+ .buffer_height_cfg = 0x00003720,
+ .packer_cfg = 0x00003724,
+ .stride = 0x00003728,
+ .irq_subsample_period = 0x00003748,
+ .irq_subsample_pattern = 0x0000374C,
+ .framedrop_period = 0x00003750,
+ .framedrop_pattern = 0x00003754,
+ .frame_inc = 0x00003758,
+ .burst_limit = 0x0000375C,
+ .ubwc_regs =
+ &vfe175_130_ubwc_regs_client_21,
+ },
+ /* BUS Client 22 */
+ {
+ .status0 = 0x00003800,
+ .status1 = 0x00003804,
+ .cfg = 0x00003808,
+ .header_addr = 0x0000380C,
+ .header_cfg = 0x00003810,
+ .image_addr = 0x00003814,
+ .image_addr_offset = 0x00003818,
+ .buffer_width_cfg = 0x0000381C,
+ .buffer_height_cfg = 0x00003820,
+ .packer_cfg = 0x00003824,
+ .stride = 0x00003828,
+ .irq_subsample_period = 0x00003848,
+ .irq_subsample_pattern = 0x0000384C,
+ .framedrop_period = 0x00003850,
+ .framedrop_pattern = 0x00003854,
+ .frame_inc = 0x00003858,
+ .burst_limit = 0x0000385C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 23 */
+ {
+ .status0 = 0x00003900,
+ .status1 = 0x00003904,
+ .cfg = 0x00003908,
+ .header_addr = 0x0000390C,
+ .header_cfg = 0x00003910,
+ .image_addr = 0x00003914,
+ .image_addr_offset = 0x00003918,
+ .buffer_width_cfg = 0x0000391C,
+ .buffer_height_cfg = 0x00003920,
+ .packer_cfg = 0x00003924,
+ .stride = 0x00003928,
+ .irq_subsample_period = 0x00003948,
+ .irq_subsample_pattern = 0x0000394C,
+ .framedrop_period = 0x00003950,
+ .framedrop_pattern = 0x00003954,
+ .frame_inc = 0x00003958,
+ .burst_limit = 0x0000395C,
+ .ubwc_regs = NULL,
+ },
+ },
+ .comp_grp_reg = {
+ /* CAM_VFE_BUS_VER2_COMP_GRP_0 */
+ {
+ .comp_mask = 0x00002010,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_1 */
+ {
+ .comp_mask = 0x00002014,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_2 */
+ {
+ .comp_mask = 0x00002018,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_3 */
+ {
+ .comp_mask = 0x0000201C,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_4 */
+ {
+ .comp_mask = 0x00002020,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_5 */
+ {
+ .comp_mask = 0x00002024,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 */
+ {
+ .comp_mask = 0x0000202C,
+ .addr_sync_mask = 0x00002088,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1 */
+ {
+ .comp_mask = 0x00002030,
+ .addr_sync_mask = 0x0000208C,
+
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2 */
+ {
+ .comp_mask = 0x00002034,
+ .addr_sync_mask = 0x00002090,
+
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3 */
+ {
+ .comp_mask = 0x00002038,
+ .addr_sync_mask = 0x00002094,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4 */
+ {
+ .comp_mask = 0x0000203C,
+ .addr_sync_mask = 0x00002098,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 */
+ {
+ .comp_mask = 0x00002040,
+ .addr_sync_mask = 0x0000209C,
+ },
+ },
+ .num_out = 22,
+ .vfe_out_hw_info = {
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI0,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI1,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI2,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_FULL,
+ .max_width = 4096,
+ .max_height = 4096,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS4,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS16,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_FD,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_PDAF,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP,
+ .max_width = 4096,
+ .max_height = 4096,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS4_DISP,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS16_DISP,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_2PD,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ },
+};
+
+struct cam_vfe_hw_info cam_vfe175_130_hw_info = {
+ .irq_reg_info = &vfe175_130_top_irq_reg_info,
+
+ .bus_version = CAM_VFE_BUS_VER_2_0,
+ .bus_hw_info = &vfe175_130_bus_hw_info,
+
+ .bus_rd_version = CAM_VFE_BUS_VER_2_0,
+ .bus_rd_hw_info = &vfe175_130_bus_rd_hw_info,
+
+ .top_version = CAM_VFE_TOP_VER_2_0,
+ .top_hw_info = &vfe175_130_top_hw_info,
+
+ .camif_version = CAM_VFE_CAMIF_VER_2_0,
+ .camif_reg = &vfe175_130_camif_reg,
+
+ .camif_lite_version = CAM_VFE_CAMIF_LITE_VER_2_0,
+ .camif_lite_reg = &vfe175_130_camif_lite_reg,
+
+};
+
+#endif /* _CAM_VFE175_130_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe17x.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe17x.c
index 6ec5ffbde4e0..2e11dc40d5a3 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe17x.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe17x.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -12,6 +12,8 @@
#include <linux/module.h>
#include "cam_vfe170.h"
+#include "cam_vfe175.h"
+#include "cam_vfe175_130.h"
#include "cam_vfe_lite17x.h"
#include "cam_vfe_hw_intf.h"
#include "cam_vfe_core.h"
@@ -23,9 +25,21 @@ static const struct of_device_id cam_vfe_dt_match[] = {
.data = &cam_vfe170_hw_info,
},
{
+ .compatible = "qcom,vfe175",
+ .data = &cam_vfe175_hw_info,
+ },
+ {
+ .compatible = "qcom,vfe175_130",
+ .data = &cam_vfe175_130_hw_info,
+ },
+ {
.compatible = "qcom,vfe-lite170",
.data = &cam_vfe_lite17x_hw_info,
},
+ {
+ .compatible = "qcom,vfe-lite175",
+ .data = &cam_vfe_lite17x_hw_info,
+ },
{}
};
MODULE_DEVICE_TABLE(of, cam_vfe_dt_match);
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile
index 1823497221ba..d8db0b56a0ee 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile
@@ -11,4 +11,4 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vf
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cpas/include
-obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_bus.o cam_vfe_bus_ver2.o
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_bus.o cam_vfe_bus_ver2.o cam_vfe_bus_rd_ver1.o
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c
index 4c0c147f4122..b0495922a90d 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,9 +13,11 @@
#include "cam_vfe_bus.h"
#include "cam_vfe_bus_ver1.h"
#include "cam_vfe_bus_ver2.h"
+#include "cam_vfe_bus_rd_ver1.h"
#include "cam_debug_util.h"
int cam_vfe_bus_init(uint32_t bus_version,
+ int bus_type,
struct cam_hw_soc_info *soc_info,
struct cam_hw_intf *hw_intf,
void *bus_hw_info,
@@ -24,10 +26,16 @@ int cam_vfe_bus_init(uint32_t bus_version,
{
int rc = -ENODEV;
- switch (bus_version) {
- case CAM_VFE_BUS_VER_2_0:
- rc = cam_vfe_bus_ver2_init(soc_info, hw_intf, bus_hw_info,
- vfe_irq_controller, vfe_bus);
+ switch (bus_type) {
+ case BUS_TYPE_WR:
+ if (CAM_VFE_BUS_VER_2_0)
+ rc = cam_vfe_bus_ver2_init(soc_info, hw_intf,
+ bus_hw_info, vfe_irq_controller, vfe_bus);
+ break;
+ case BUS_TYPE_RD:
+ /* Call vfe bus rd init function */
+ rc = cam_vfe_bus_rd_ver1_init(soc_info, hw_intf,
+ bus_hw_info, vfe_irq_controller, vfe_bus);
break;
default:
CAM_ERR(CAM_ISP, "Unsupported Bus Version %x", bus_version);
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c
new file mode 100644
index 000000000000..5474ead1826e
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c
@@ -0,0 +1,1239 @@
+/* Copyright (c) 2018, 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/ratelimit.h>
+#include <linux/slab.h>
+#include <uapi/media/cam_isp.h>
+#include "cam_io_util.h"
+#include "cam_debug_util.h"
+#include "cam_cdm_util.h"
+#include "cam_hw_intf.h"
+#include "cam_ife_hw_mgr.h"
+#include "cam_vfe_hw_intf.h"
+#include "cam_irq_controller.h"
+#include "cam_tasklet_util.h"
+#include "cam_vfe_bus.h"
+#include "cam_vfe_bus_rd_ver1.h"
+#include "cam_vfe_core.h"
+#include "cam_debug_util.h"
+#include "cam_cpas_api.h"
+
+static const char drv_name[] = "vfe_bus_rd";
+
+#define ALIGNUP(value, alignment) \
+ ((value + alignment - 1) / alignment * alignment)
+
+#define MAX_BUF_UPDATE_REG_NUM \
+ (sizeof(struct cam_vfe_bus_rd_ver1_reg_offset_bus_client)/4)
+
+#define MAX_REG_VAL_PAIR_SIZE \
+ (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES)
+
+#define CAM_VFE_ADD_REG_VAL_PAIR(buf_array, index, offset, val) \
+ do { \
+ buf_array[(index)++] = offset; \
+ buf_array[(index)++] = val; \
+ } while (0)
+
+enum cam_vfe_bus_rd_ver1_unpacker_format {
+ BUS_RD_VER1_PACKER_FMT_PLAIN_128 = 0x0,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_8 = 0x1,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_16_10BPP = 0x2,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_16_12BPP = 0x3,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_16_14BPP = 0x4,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_16_16BPP = 0x5,
+ BUS_RD_VER1_PACKER_FMT_ARGB_10 = 0x6,
+ BUS_RD_VER1_PACKER_FMT_ARGB_12 = 0x7,
+ BUS_RD_VER1_PACKER_FMT_ARGB_14 = 0x8,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_32_20BPP = 0x9,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_64 = 0xA,
+ BUS_RD_VER1_PACKER_FMT_TP_10 = 0xB,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_32_32BPP = 0xC,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_8_ODD_EVEN = 0xD,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_8_LSB_MSB_10 = 0xE,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_8_LSB_MSB_10_ODD_EVEN = 0xF,
+ BUS_RD_VER1_PACKER_FMT_MAX = 0xF,
+};
+
+struct cam_vfe_bus_rd_ver1_common_data {
+ uint32_t core_index;
+ void __iomem *mem_base;
+ struct cam_hw_intf *hw_intf;
+ void *bus_irq_controller;
+ void *vfe_irq_controller;
+ struct cam_vfe_bus_rd_ver1_reg_offset_common *common_reg;
+ uint32_t io_buf_update[
+ MAX_REG_VAL_PAIR_SIZE];
+
+ struct list_head free_payload_list;
+ spinlock_t spin_lock;
+ struct mutex bus_mutex;
+ uint32_t secure_mode;
+ uint32_t num_sec_out;
+ uint32_t fs_sync_enable;
+ uint32_t go_cmd_sel;
+};
+
+struct cam_vfe_bus_rd_ver1_rm_resource_data {
+ uint32_t index;
+ struct cam_vfe_bus_rd_ver1_common_data *common_data;
+ struct cam_vfe_bus_rd_ver1_reg_offset_bus_client *hw_regs;
+ void *ctx;
+
+ uint32_t irq_enabled;
+ bool init_cfg_done;
+ bool hfr_cfg_done;
+
+ uint32_t offset;
+
+ uint32_t min_vbi;
+ uint32_t fs_mode;
+ uint32_t hbi_count;
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
+ uint32_t format;
+ uint32_t latency_buf_allocation;
+ uint32_t unpacker_cfg;
+ uint32_t burst_len;
+
+ uint32_t go_cmd_sel;
+ uint32_t fs_sync_enable;
+ uint32_t fs_line_sync_en;
+
+ uint32_t en_cfg;
+ uint32_t is_dual;
+ uint32_t img_addr;
+ uint32_t input_if_cmd;
+};
+
+struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data {
+ uint32_t bus_rd_type;
+ struct cam_vfe_bus_rd_ver1_common_data *common_data;
+
+ uint32_t num_rm;
+ struct cam_isp_resource_node *rm_res[PLANE_MAX];
+
+ struct cam_isp_resource_node *comp_grp;
+ enum cam_isp_hw_sync_mode dual_comp_sync_mode;
+ uint32_t dual_hw_alternate_vfe_id;
+ struct list_head vfe_bus_rd_list;
+
+ uint32_t format;
+ uint32_t max_width;
+ uint32_t max_height;
+ struct cam_cdm_utils_ops *cdm_util_ops;
+ uint32_t secure_mode;
+};
+
+struct cam_vfe_bus_rd_ver1_priv {
+ struct cam_vfe_bus_rd_ver1_common_data common_data;
+ uint32_t num_client;
+ uint32_t num_bus_rd_resc;
+
+ struct cam_isp_resource_node bus_client[
+ CAM_VFE_BUS_RD_VER1_MAX_CLIENTS];
+ struct cam_isp_resource_node vfe_bus_rd[
+ CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX];
+
+ uint32_t irq_handle;
+ uint32_t error_irq_handle;
+};
+
+static int cam_vfe_bus_process_cmd(
+ struct cam_isp_resource_node *priv,
+ uint32_t cmd_type, void *cmd_args, uint32_t arg_size);
+
+static enum cam_vfe_bus_rd_ver1_unpacker_format
+ cam_vfe_bus_get_unpacker_fmt(uint32_t unpack_fmt)
+{
+ switch (unpack_fmt) {
+ case CAM_FORMAT_MIPI_RAW_10:
+ return BUS_RD_VER1_PACKER_FMT_PLAIN_8_ODD_EVEN;
+ default:
+ return BUS_RD_VER1_PACKER_FMT_MAX;
+ }
+}
+
+static bool cam_vfe_bus_can_be_secure(uint32_t out_type)
+{
+ switch (out_type) {
+ case CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0:
+ return false;
+
+ default:
+ return false;
+ }
+}
+
+static enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type
+ cam_vfe_bus_get_bus_rd_res_id(uint32_t res_type)
+{
+ switch (res_type) {
+ case CAM_ISP_RESOURCE_VFE_BUS_RD:
+ return CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0;
+ default:
+ return CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX;
+ }
+}
+
+static int cam_vfe_bus_get_num_rm(
+ enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type res_type)
+{
+ switch (res_type) {
+ case CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0:
+ return 1;
+ default:
+ break;
+ }
+
+ CAM_ERR(CAM_ISP, "Unsupported resource_type %u",
+ res_type);
+ return -EINVAL;
+}
+
+static int cam_vfe_bus_get_rm_idx(
+ enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type vfe_bus_rd_res_id,
+ enum cam_vfe_bus_plane_type plane)
+{
+ int rm_idx = -1;
+
+ switch (vfe_bus_rd_res_id) {
+ case CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0:
+ switch (plane) {
+ case PLANE_Y:
+ rm_idx = 0;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return rm_idx;
+}
+
+static int cam_vfe_bus_acquire_rm(
+ struct cam_vfe_bus_rd_ver1_priv *ver1_bus_rd_priv,
+ struct cam_isp_out_port_info *out_port_info,
+ void *tasklet,
+ void *ctx,
+ enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type vfe_bus_rd_res_id,
+ enum cam_vfe_bus_plane_type plane,
+ uint32_t subscribe_irq,
+ struct cam_isp_resource_node **rm_res,
+ uint32_t *client_done_mask,
+ uint32_t is_dual)
+{
+ uint32_t rm_idx = 0;
+ struct cam_isp_resource_node *rm_res_local = NULL;
+ struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data = NULL;
+
+ *rm_res = NULL;
+ *client_done_mask = 0;
+
+ /* No need to allocate for BUS VER2. VFE OUT to RM is fixed. */
+ rm_idx = cam_vfe_bus_get_rm_idx(vfe_bus_rd_res_id, plane);
+ if (rm_idx < 0 || rm_idx >= ver1_bus_rd_priv->num_client) {
+ CAM_ERR(CAM_ISP, "Unsupported VFE out %d plane %d",
+ vfe_bus_rd_res_id, plane);
+ return -EINVAL;
+ }
+
+ rm_res_local = &ver1_bus_rd_priv->bus_client[rm_idx];
+ if (rm_res_local->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
+ CAM_ERR(CAM_ISP, "RM res not available state:%d",
+ rm_res_local->res_state);
+ return -EALREADY;
+ }
+ rm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+ rm_res_local->tasklet_info = tasklet;
+
+ rsrc_data = rm_res_local->res_priv;
+ rsrc_data->irq_enabled = subscribe_irq;
+ rsrc_data->ctx = ctx;
+ rsrc_data->is_dual = is_dual;
+ /* Set RM offset value to default */
+ rsrc_data->offset = 0;
+
+ *client_done_mask = (1 << rm_idx);
+ *rm_res = rm_res_local;
+
+ CAM_DBG(CAM_ISP, "RM %d: Acquired");
+ return 0;
+}
+
+static int cam_vfe_bus_release_rm(void *bus_priv,
+ struct cam_isp_resource_node *rm_res)
+{
+ struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data =
+ rm_res->res_priv;
+
+ rsrc_data->irq_enabled = 0;
+ rsrc_data->offset = 0;
+ rsrc_data->width = 0;
+ rsrc_data->height = 0;
+ rsrc_data->stride = 0;
+ rsrc_data->format = 0;
+ rsrc_data->unpacker_cfg = 0;
+ rsrc_data->burst_len = 0;
+ rsrc_data->init_cfg_done = false;
+ rsrc_data->hfr_cfg_done = false;
+ rsrc_data->en_cfg = 0;
+ rsrc_data->is_dual = 0;
+
+ rm_res->tasklet_info = NULL;
+ rm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
+
+ return 0;
+}
+
+static int cam_vfe_bus_start_rm(struct cam_isp_resource_node *rm_res)
+{
+ int rc = 0;
+ struct cam_vfe_bus_rd_ver1_rm_resource_data *rm_data =
+ rm_res->res_priv;
+ struct cam_vfe_bus_rd_ver1_common_data *common_data =
+ rm_data->common_data;
+ uint32_t buf_size;
+ uint32_t val;
+ uint32_t offset;
+
+ CAM_DBG(CAM_ISP, "w: 0x%x", rm_data->width);
+ CAM_DBG(CAM_ISP, "h: 0x%x", rm_data->height);
+ CAM_DBG(CAM_ISP, "format: 0x%x", rm_data->format);
+ CAM_DBG(CAM_ISP, "unpacker_cfg: 0x%x", rm_data->unpacker_cfg);
+ CAM_DBG(CAM_ISP, "latency_buf_allocation: 0x%x",
+ rm_data->latency_buf_allocation);
+ CAM_DBG(CAM_ISP, "stride: 0x%x", rm_data->stride);
+ CAM_DBG(CAM_ISP, "go_cmd_sel: 0x%x", rm_data->go_cmd_sel);
+ CAM_DBG(CAM_ISP, "fs_sync_enable: 0x%x", rm_data->fs_sync_enable);
+ CAM_DBG(CAM_ISP, "hbi_count: 0x%x", rm_data->hbi_count);
+ CAM_DBG(CAM_ISP, "fs_line_sync_en: 0x%x", rm_data->fs_line_sync_en);
+ CAM_DBG(CAM_ISP, "fs_mode: 0x%x", rm_data->fs_mode);
+ CAM_DBG(CAM_ISP, "min_vbi: 0x%x", rm_data->min_vbi);
+
+ /* Write All the values*/
+ offset = rm_data->hw_regs->buffer_width_cfg;
+ buf_size = ((rm_data->width)&(0x0000FFFF)) |
+ ((rm_data->height<<16)&(0xFFFF0000));
+ cam_io_w_mb(buf_size, common_data->mem_base + offset);
+ CAM_DBG(CAM_ISP, "buf_size: 0x%x", buf_size);
+
+ val = rm_data->width;
+ offset = rm_data->hw_regs->stride;
+ CAM_DBG(CAM_ISP, "offset:0x%x, value:0x%x", offset, val);
+ cam_io_w_mb(val, common_data->mem_base + offset);
+
+ CAM_DBG(CAM_ISP, "rm_data->unpacker_cfg:0x%x", rm_data->unpacker_cfg);
+ val = cam_vfe_bus_get_unpacker_fmt(rm_data->unpacker_cfg);
+ CAM_DBG(CAM_ISP, " value:0x%x", val);
+ offset = rm_data->hw_regs->unpacker_cfg;
+ CAM_DBG(CAM_ISP, "offset:0x%x, value:0x%x", offset, val);
+ cam_io_w_mb(val, common_data->mem_base + offset);
+
+ val = rm_data->latency_buf_allocation;
+ offset = rm_data->hw_regs->latency_buf_allocation;
+ CAM_DBG(CAM_ISP, "offset:0x%x, value:0x%x", offset, val);
+ cam_io_w_mb(val, common_data->mem_base + offset);
+
+ cam_io_w_mb(0x1, common_data->mem_base +
+ rm_data->hw_regs->cfg);
+ return rc;
+}
+
+static int cam_vfe_bus_stop_rm(struct cam_isp_resource_node *rm_res)
+{
+ int rc = 0;
+ struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data =
+ rm_res->res_priv;
+ struct cam_vfe_bus_rd_ver1_common_data *common_data =
+ rsrc_data->common_data;
+
+ /* Disable RM */
+ cam_io_w_mb(0x0,
+ common_data->mem_base + rsrc_data->hw_regs->cfg);
+
+ rm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+ rsrc_data->init_cfg_done = false;
+ rsrc_data->hfr_cfg_done = false;
+
+ return rc;
+}
+
+static int cam_vfe_bus_init_rm_resource(uint32_t index,
+ struct cam_vfe_bus_rd_ver1_priv *ver1_bus_rd_priv,
+ struct cam_vfe_bus_rd_ver1_hw_info *bus_rd_hw_info,
+ struct cam_isp_resource_node *rm_res)
+{
+ struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data;
+
+ rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_rd_ver1_rm_resource_data),
+ GFP_KERNEL);
+ if (!rsrc_data) {
+ CAM_DBG(CAM_ISP, "Failed to alloc for RM res priv");
+ return -ENOMEM;
+ }
+ rm_res->res_priv = rsrc_data;
+
+ rsrc_data->index = index;
+ rsrc_data->hw_regs = &bus_rd_hw_info->bus_client_reg[index];
+ rsrc_data->common_data = &ver1_bus_rd_priv->common_data;
+
+ rm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
+ INIT_LIST_HEAD(&rm_res->list);
+
+ rm_res->start = cam_vfe_bus_start_rm;
+ rm_res->stop = cam_vfe_bus_stop_rm;
+ rm_res->hw_intf = ver1_bus_rd_priv->common_data.hw_intf;
+
+
+ return 0;
+}
+
+static int cam_vfe_bus_deinit_rm_resource(
+ struct cam_isp_resource_node *rm_res)
+{
+ struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data;
+
+ rm_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
+ INIT_LIST_HEAD(&rm_res->list);
+
+ rm_res->start = NULL;
+ rm_res->stop = NULL;
+ rm_res->top_half_handler = NULL;
+ rm_res->bottom_half_handler = NULL;
+ rm_res->hw_intf = NULL;
+
+ rsrc_data = rm_res->res_priv;
+ rm_res->res_priv = NULL;
+ if (!rsrc_data)
+ return -ENOMEM;
+ kfree(rsrc_data);
+
+ return 0;
+}
+
+static int cam_vfe_bus_rd_get_secure_mode(void *priv, void *cmd_args,
+ uint32_t arg_size)
+{
+ return 0;
+}
+
+static int cam_vfe_bus_acquire_vfe_bus_rd(void *bus_priv, void *acquire_args,
+ uint32_t args_size)
+{
+ int rc = -ENODEV;
+ int i;
+ enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type bus_rd_res_id;
+ int num_rm;
+ uint32_t subscribe_irq;
+ uint32_t client_done_mask;
+ struct cam_vfe_bus_rd_ver1_priv *ver1_bus_rd_priv =
+ bus_priv;
+ struct cam_vfe_acquire_args *acq_args = acquire_args;
+ struct cam_vfe_hw_vfe_out_acquire_args *bus_rd_acquire_args;
+ struct cam_isp_resource_node *rsrc_node = NULL;
+ struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL;
+ uint32_t secure_caps = 0, mode;
+
+ if (!bus_priv || !acquire_args) {
+ CAM_ERR(CAM_ISP, "Invalid Param");
+ return -EINVAL;
+ }
+
+ bus_rd_acquire_args = &acq_args->vfe_bus_rd;
+
+ CAM_DBG(CAM_ISP, "Acquiring resource type 0x%x",
+ acq_args->rsrc_type);
+
+ bus_rd_res_id = cam_vfe_bus_get_bus_rd_res_id(
+ acq_args->rsrc_type);
+ if (bus_rd_res_id == CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX)
+ return -ENODEV;
+
+ num_rm = cam_vfe_bus_get_num_rm(bus_rd_res_id);
+ if (num_rm < 1)
+ return -EINVAL;
+
+ rsrc_node = &ver1_bus_rd_priv->vfe_bus_rd[bus_rd_res_id];
+ if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
+ CAM_ERR(CAM_ISP, "Resource not available: Res_id %d state:%d",
+ bus_rd_res_id, rsrc_node->res_state);
+ return -EBUSY;
+ }
+
+ rsrc_data = rsrc_node->res_priv;
+ secure_caps = cam_vfe_bus_can_be_secure(
+ rsrc_data->bus_rd_type);
+
+ mode = bus_rd_acquire_args->out_port_info->secure_mode;
+ mutex_lock(&rsrc_data->common_data->bus_mutex);
+ if (secure_caps) {
+ if (!rsrc_data->common_data->num_sec_out) {
+ rsrc_data->secure_mode = mode;
+ rsrc_data->common_data->secure_mode = mode;
+ } else {
+ if (mode == rsrc_data->common_data->secure_mode) {
+ rsrc_data->secure_mode =
+ rsrc_data->common_data->secure_mode;
+ } else {
+ rc = -EINVAL;
+ CAM_ERR_RATE_LIMIT(CAM_ISP,
+ "Mismatch: Acquire mode[%d], drvr mode[%d]",
+ rsrc_data->common_data->secure_mode,
+ mode);
+ mutex_unlock(
+ &rsrc_data->common_data->bus_mutex);
+ return -EINVAL;
+ }
+ }
+ rsrc_data->common_data->num_sec_out++;
+ }
+ mutex_unlock(&rsrc_data->common_data->bus_mutex);
+
+ rsrc_data->num_rm = num_rm;
+ rsrc_node->tasklet_info = acq_args->tasklet;
+ rsrc_node->cdm_ops = bus_rd_acquire_args->cdm_ops;
+ rsrc_data->cdm_util_ops = bus_rd_acquire_args->cdm_ops;
+
+ subscribe_irq = 1;
+
+ for (i = 0; i < num_rm; i++) {
+ rc = cam_vfe_bus_acquire_rm(ver1_bus_rd_priv,
+ bus_rd_acquire_args->out_port_info,
+ acq_args->tasklet,
+ bus_rd_acquire_args->ctx,
+ bus_rd_res_id,
+ i,
+ subscribe_irq,
+ &rsrc_data->rm_res[i],
+ &client_done_mask,
+ bus_rd_acquire_args->is_dual);
+ if (rc) {
+ CAM_ERR(CAM_ISP,
+ "VFE%d RM acquire failed for Out %d rc=%d",
+ rsrc_data->common_data->core_index,
+ bus_rd_res_id, rc);
+ goto release_rm;
+ }
+ }
+
+ rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+ bus_rd_acquire_args->rsrc_node = rsrc_node;
+
+ CAM_DBG(CAM_ISP, "Acquire successful");
+ return rc;
+
+release_rm:
+ for (i--; i >= 0; i--)
+ cam_vfe_bus_release_rm(ver1_bus_rd_priv, rsrc_data->rm_res[i]);
+ return rc;
+}
+
+static int cam_vfe_bus_release_vfe_bus_rd(void *bus_priv, void *release_args,
+ uint32_t args_size)
+{
+ uint32_t i;
+ struct cam_isp_resource_node *vfe_bus_rd = NULL;
+ struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL;
+ uint32_t secure_caps = 0;
+
+ if (!bus_priv || !release_args) {
+ CAM_ERR(CAM_ISP, "Invalid input bus_priv %pK release_args %pK",
+ bus_priv, release_args);
+ return -EINVAL;
+ }
+
+ vfe_bus_rd = release_args;
+ rsrc_data = vfe_bus_rd->res_priv;
+
+ if (vfe_bus_rd->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
+ CAM_ERR(CAM_ISP, "Invalid resource state:%d",
+ vfe_bus_rd->res_state);
+ }
+
+ for (i = 0; i < rsrc_data->num_rm; i++)
+ cam_vfe_bus_release_rm(bus_priv, rsrc_data->rm_res[i]);
+ rsrc_data->num_rm = 0;
+
+ vfe_bus_rd->tasklet_info = NULL;
+ vfe_bus_rd->cdm_ops = NULL;
+ rsrc_data->cdm_util_ops = NULL;
+
+ secure_caps = cam_vfe_bus_can_be_secure(rsrc_data->bus_rd_type);
+ mutex_lock(&rsrc_data->common_data->bus_mutex);
+ if (secure_caps) {
+ if (rsrc_data->secure_mode ==
+ rsrc_data->common_data->secure_mode) {
+ rsrc_data->common_data->num_sec_out--;
+ rsrc_data->secure_mode =
+ CAM_SECURE_MODE_NON_SECURE;
+ } else {
+ /*
+ * The validity of the mode is properly
+ * checked while acquiring the output port.
+ * not expected to reach here, unless there is
+ * some corruption.
+ */
+ CAM_ERR(CAM_ISP, "driver[%d],resource[%d] mismatch",
+ rsrc_data->common_data->secure_mode,
+ rsrc_data->secure_mode);
+ }
+
+ if (!rsrc_data->common_data->num_sec_out)
+ rsrc_data->common_data->secure_mode =
+ CAM_SECURE_MODE_NON_SECURE;
+ }
+ mutex_unlock(&rsrc_data->common_data->bus_mutex);
+
+ if (vfe_bus_rd->res_state == CAM_ISP_RESOURCE_STATE_RESERVED)
+ vfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
+
+ return 0;
+}
+
+static int cam_vfe_bus_start_vfe_bus_rd(
+ struct cam_isp_resource_node *vfe_out)
+{
+ int rc = 0, i;
+ struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL;
+ struct cam_vfe_bus_rd_ver1_common_data *common_data = NULL;
+
+ if (!vfe_out) {
+ CAM_ERR(CAM_ISP, "Invalid input");
+ return -EINVAL;
+ }
+
+ rsrc_data = vfe_out->res_priv;
+ common_data = rsrc_data->common_data;
+
+ CAM_DBG(CAM_ISP, "Start resource type: %x", rsrc_data->bus_rd_type);
+
+ if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
+ CAM_ERR(CAM_ISP, "Invalid resource state:%d",
+ vfe_out->res_state);
+ return -EACCES;
+ }
+
+ for (i = 0; i < rsrc_data->num_rm; i++)
+ rc = cam_vfe_bus_start_rm(rsrc_data->rm_res[i]);
+ vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
+ return rc;
+}
+
+static int cam_vfe_bus_stop_vfe_bus_rd(
+ struct cam_isp_resource_node *vfe_bus_rd)
+{
+ int rc = 0, i;
+ struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL;
+
+ CAM_DBG(CAM_ISP, "E:Stop rd Res");
+ if (!vfe_bus_rd) {
+ CAM_ERR(CAM_ISP, "Invalid input");
+ return -EINVAL;
+ }
+
+ rsrc_data = vfe_bus_rd->res_priv;
+
+ if (vfe_bus_rd->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
+ vfe_bus_rd->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
+ CAM_DBG(CAM_ISP, "vfe_out res_state is %d",
+ vfe_bus_rd->res_state);
+ return rc;
+ }
+ for (i = 0; i < rsrc_data->num_rm; i++)
+ rc = cam_vfe_bus_stop_rm(rsrc_data->rm_res[i]);
+
+ vfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+ return rc;
+}
+
+static int cam_vfe_bus_init_vfe_bus_read_resource(uint32_t index,
+ struct cam_vfe_bus_rd_ver1_priv *bus_rd_priv,
+ struct cam_vfe_bus_rd_ver1_hw_info *bus_rd_hw_info)
+{
+ struct cam_isp_resource_node *vfe_bus_rd = NULL;
+ struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL;
+ int rc = 0;
+ int32_t vfe_bus_rd_resc_type =
+ bus_rd_hw_info->vfe_bus_rd_hw_info[index].vfe_bus_rd_type;
+
+ if (vfe_bus_rd_resc_type < 0 ||
+ vfe_bus_rd_resc_type > CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0) {
+ CAM_ERR(CAM_ISP, "Init VFE Out failed, Invalid type=%d",
+ vfe_bus_rd_resc_type);
+ return -EINVAL;
+ }
+
+ vfe_bus_rd = &bus_rd_priv->vfe_bus_rd[vfe_bus_rd_resc_type];
+ if (vfe_bus_rd->res_state != CAM_ISP_RESOURCE_STATE_UNAVAILABLE ||
+ vfe_bus_rd->res_priv) {
+ CAM_ERR(CAM_ISP,
+ "Error. Looks like same resource is init again");
+ return -EFAULT;
+ }
+
+ rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data),
+ GFP_KERNEL);
+ if (!rsrc_data) {
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ vfe_bus_rd->res_priv = rsrc_data;
+
+ vfe_bus_rd->res_type = CAM_ISP_RESOURCE_VFE_BUS_RD;
+ vfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
+ INIT_LIST_HEAD(&vfe_bus_rd->list);
+
+ rsrc_data->bus_rd_type =
+ bus_rd_hw_info->vfe_bus_rd_hw_info[index].vfe_bus_rd_type;
+ rsrc_data->common_data = &bus_rd_priv->common_data;
+ rsrc_data->max_width =
+ bus_rd_hw_info->vfe_bus_rd_hw_info[index].max_width;
+ rsrc_data->max_height =
+ bus_rd_hw_info->vfe_bus_rd_hw_info[index].max_height;
+ rsrc_data->secure_mode = CAM_SECURE_MODE_NON_SECURE;
+
+ vfe_bus_rd->start = cam_vfe_bus_start_vfe_bus_rd;
+ vfe_bus_rd->stop = cam_vfe_bus_stop_vfe_bus_rd;
+ vfe_bus_rd->process_cmd = cam_vfe_bus_process_cmd;
+ vfe_bus_rd->hw_intf = bus_rd_priv->common_data.hw_intf;
+
+ return 0;
+}
+
+static int cam_vfe_bus_deinit_vfe_bus_rd_resource(
+ struct cam_isp_resource_node *vfe_bus_rd_res)
+{
+ struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data =
+ vfe_bus_rd_res->res_priv;
+
+ if (vfe_bus_rd_res->res_state == CAM_ISP_RESOURCE_STATE_UNAVAILABLE) {
+ /*
+ * This is not error. It can happen if the resource is
+ * never supported in the HW.
+ */
+ CAM_DBG(CAM_ISP, "HW%d Res %d already deinitialized");
+ return 0;
+ }
+
+ vfe_bus_rd_res->start = NULL;
+ vfe_bus_rd_res->stop = NULL;
+ vfe_bus_rd_res->top_half_handler = NULL;
+ vfe_bus_rd_res->bottom_half_handler = NULL;
+ vfe_bus_rd_res->hw_intf = NULL;
+
+ vfe_bus_rd_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
+ INIT_LIST_HEAD(&vfe_bus_rd_res->list);
+ vfe_bus_rd_res->res_priv = NULL;
+
+ if (!rsrc_data)
+ return -ENOMEM;
+ kfree(rsrc_data);
+
+ return 0;
+}
+
+static int cam_vfe_bus_rd_ver1_handle_irq(uint32_t evt_id,
+ struct cam_irq_th_payload *th_payload)
+{
+ struct cam_vfe_bus_rd_ver1_priv *bus_priv;
+
+ bus_priv = th_payload->handler_priv;
+ CAM_DBG(CAM_ISP, "BUS READ IRQ Received");
+ return 0;
+}
+
+static int cam_vfe_bus_rd_update_rm(void *priv, void *cmd_args,
+ uint32_t arg_size)
+{
+ struct cam_vfe_bus_rd_ver1_priv *bus_priv;
+ struct cam_isp_hw_get_cmd_update *update_buf;
+ struct cam_buf_io_cfg *io_cfg;
+ struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *vfe_bus_rd_data = NULL;
+ struct cam_vfe_bus_rd_ver1_rm_resource_data *rm_data = NULL;
+ uint32_t *reg_val_pair;
+ uint32_t i, j, size = 0;
+ uint32_t val;
+ uint32_t buf_size = 0;
+
+ bus_priv = (struct cam_vfe_bus_rd_ver1_priv *) priv;
+ update_buf = (struct cam_isp_hw_get_cmd_update *) cmd_args;
+
+ vfe_bus_rd_data = (struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *)
+ update_buf->res->res_priv;
+
+ if (!vfe_bus_rd_data || !vfe_bus_rd_data->cdm_util_ops) {
+ CAM_ERR(CAM_ISP, "Failed! Invalid data");
+ return -EINVAL;
+ }
+
+ CAM_DBG(CAM_ISP, "#of RM: %d", vfe_bus_rd_data->num_rm);
+ if (update_buf->rm_update->num_buf != vfe_bus_rd_data->num_rm) {
+ CAM_ERR(CAM_ISP,
+ "Failed! Invalid number buffers:%d required:%d",
+ update_buf->rm_update->num_buf,
+ vfe_bus_rd_data->num_rm);
+ return -EINVAL;
+ }
+
+ reg_val_pair = &vfe_bus_rd_data->common_data->io_buf_update[0];
+ io_cfg = update_buf->rm_update->io_cfg;
+
+ for (i = 0, j = 0; i < vfe_bus_rd_data->num_rm; i++) {
+ if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
+ CAM_ERR(CAM_ISP,
+ "reg_val_pair %d exceeds the array limit %lu",
+ j, MAX_REG_VAL_PAIR_SIZE);
+ return -ENOMEM;
+ }
+
+ rm_data = vfe_bus_rd_data->rm_res[i]->res_priv;
+
+ /* update size register */
+ rm_data->width = io_cfg->planes[i].width;
+ rm_data->height = io_cfg->planes[i].height;
+ CAM_DBG(CAM_ISP, "RM %d image w 0x%x h 0x%x image size 0x%x",
+ rm_data->index, rm_data->width, rm_data->height,
+ buf_size);
+
+ buf_size = ((rm_data->width)&(0x0000FFFF)) |
+ ((rm_data->height<<16)&(0xFFFF0000));
+
+ CAM_DBG(CAM_ISP, "size offset 0x%x buf_size 0x%x",
+ rm_data->hw_regs->buf_size, buf_size);
+ CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+ rm_data->hw_regs->buffer_width_cfg,
+ buf_size);
+ CAM_DBG(CAM_ISP, "RM %d image size 0x%x",
+ rm_data->index, reg_val_pair[j-1]);
+
+ val = rm_data->width;
+ CAM_DBG(CAM_ISP, "io_cfg stride 0x%x", val);
+ CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+ rm_data->hw_regs->stride,
+ val);
+ rm_data->stride = val;
+ CAM_DBG(CAM_ISP, "RM %d image stride 0x%x",
+ rm_data->index, reg_val_pair[j-1]);
+
+ /* RM Image address */
+ CAM_DBG(CAM_ISP, "image_addr offset %x",
+ rm_data->hw_regs->image_addr);
+ CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+ rm_data->hw_regs->image_addr,
+ update_buf->rm_update->image_buf[i] +
+ rm_data->offset);
+ CAM_DBG(CAM_ISP, "RM %d image address 0x%x",
+ rm_data->index, reg_val_pair[j-1]);
+ rm_data->img_addr = reg_val_pair[j-1];
+
+ }
+
+ size = vfe_bus_rd_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
+
+ /* cdm util returns dwords, need to convert to bytes */
+ if ((size * 4) > update_buf->cmd.size) {
+ CAM_ERR(CAM_ISP,
+ "Failed! Buf size:%d insufficient, expected size:%d",
+ update_buf->cmd.size, size);
+ return -ENOMEM;
+ }
+
+ vfe_bus_rd_data->cdm_util_ops->cdm_write_regrandom(
+ update_buf->cmd.cmd_buf_addr, j/2, reg_val_pair);
+
+ /* cdm util returns dwords, need to convert to bytes */
+ update_buf->cmd.used_bytes = size * 4;
+
+ return 0;
+}
+
+static int cam_vfe_bus_rd_update_hfr(void *priv, void *cmd_args,
+ uint32_t arg_size)
+{
+ return 0;
+}
+
+static int cam_vfe_bus_rd_update_fs_cfg(void *priv, void *cmd_args,
+ uint32_t arg_size)
+{
+ struct cam_vfe_bus_rd_ver1_priv *bus_priv;
+ struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *vfe_bus_rd_data = NULL;
+ struct cam_vfe_bus_rd_ver1_rm_resource_data *rm_data = NULL;
+ struct cam_vfe_fe_update_args *fe_upd_args;
+ struct cam_fe_config *fe_cfg;
+ struct cam_vfe_bus_rd_ver1_common_data *common_data;
+ int i = 0;
+
+ bus_priv = (struct cam_vfe_bus_rd_ver1_priv *) priv;
+ fe_upd_args = (struct cam_vfe_fe_update_args *)cmd_args;
+
+ vfe_bus_rd_data = (struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *)
+ fe_upd_args->node_res->res_priv;
+
+ if (!vfe_bus_rd_data || !vfe_bus_rd_data->cdm_util_ops) {
+ CAM_ERR(CAM_ISP, "Failed! Invalid data");
+ return -EINVAL;
+ }
+
+ fe_cfg = &fe_upd_args->fe_config;
+
+ for (i = 0; i < vfe_bus_rd_data->num_rm; i++) {
+
+ rm_data = vfe_bus_rd_data->rm_res[i]->res_priv;
+ common_data = rm_data->common_data;
+
+ rm_data->format = fe_cfg->format;
+ CAM_DBG(CAM_ISP, "format: 0x%x", rm_data->format);
+
+ rm_data->unpacker_cfg = fe_cfg->unpacker_cfg;
+ CAM_DBG(CAM_ISP, "unpacker_cfg: 0x%x", rm_data->unpacker_cfg);
+
+ rm_data->latency_buf_allocation = fe_cfg->latency_buf_size;
+ CAM_DBG(CAM_ISP, "latency_buf_allocation: 0x%x",
+ rm_data->latency_buf_allocation);
+
+ rm_data->stride = fe_cfg->stride;
+ CAM_DBG(CAM_ISP, "stride: 0x%x", rm_data->stride);
+
+ rm_data->go_cmd_sel = fe_cfg->go_cmd_sel;
+ CAM_DBG(CAM_ISP, "go_cmd_sel: 0x%x", rm_data->go_cmd_sel);
+
+ rm_data->fs_sync_enable = fe_cfg->fs_sync_enable;
+ CAM_DBG(CAM_ISP, "fs_sync_enable: 0x%x",
+ rm_data->fs_sync_enable);
+
+ rm_data->hbi_count = fe_cfg->hbi_count;
+ CAM_DBG(CAM_ISP, "hbi_count: 0x%x", rm_data->hbi_count);
+
+ rm_data->fs_line_sync_en = fe_cfg->fs_line_sync_en;
+ CAM_DBG(CAM_ISP, "fs_line_sync_en: 0x%x",
+ rm_data->fs_line_sync_en);
+
+ rm_data->fs_mode = fe_cfg->fs_mode;
+ CAM_DBG(CAM_ISP, "fs_mode: 0x%x", rm_data->fs_mode);
+
+ rm_data->min_vbi = fe_cfg->min_vbi;
+ CAM_DBG(CAM_ISP, "min_vbi: 0x%x", rm_data->min_vbi);
+ }
+ bus_priv->common_data.fs_sync_enable = fe_cfg->fs_sync_enable;
+ bus_priv->common_data.go_cmd_sel = fe_cfg->go_cmd_sel;
+ return 0;
+}
+
+static int cam_vfe_bus_start_hw(void *hw_priv,
+ void *start_hw_args, uint32_t arg_size)
+{
+ return cam_vfe_bus_start_vfe_bus_rd(hw_priv);
+}
+
+static int cam_vfe_bus_stop_hw(void *hw_priv,
+ void *stop_hw_args, uint32_t arg_size)
+{
+ return cam_vfe_bus_stop_vfe_bus_rd(hw_priv);
+}
+
+static int cam_vfe_bus_init_hw(void *hw_priv,
+ void *init_hw_args, uint32_t arg_size)
+{
+ struct cam_vfe_bus_rd_ver1_priv *bus_priv = hw_priv;
+ uint32_t top_irq_reg_mask[2] = {0};
+ uint32_t offset = 0, val = 0;
+ struct cam_vfe_bus_rd_ver1_reg_offset_common *common_reg;
+
+ if (!bus_priv) {
+ CAM_ERR(CAM_ISP, "Invalid args");
+ return -EINVAL;
+ }
+ common_reg = bus_priv->common_data.common_reg;
+ top_irq_reg_mask[0] = (1 << 23);
+
+ bus_priv->irq_handle = cam_irq_controller_subscribe_irq(
+ bus_priv->common_data.vfe_irq_controller,
+ CAM_IRQ_PRIORITY_2,
+ top_irq_reg_mask,
+ bus_priv,
+ cam_vfe_bus_rd_ver1_handle_irq,
+ NULL,
+ NULL,
+ NULL);
+
+ if (bus_priv->irq_handle <= 0) {
+ CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ");
+ return -EFAULT;
+ }
+ /* no clock gating at bus input */
+ offset = common_reg->cgc_ovd;
+ cam_io_w_mb(0x0, bus_priv->common_data.mem_base + offset);
+
+ /* BUS_RD_TEST_BUS_CTRL */
+ offset = common_reg->test_bus_ctrl;
+ cam_io_w_mb(0x0, bus_priv->common_data.mem_base + offset);
+
+ /* Read irq mask */
+ offset = common_reg->irq_reg_info.irq_reg_set->mask_reg_offset;
+ cam_io_w_mb(0x5, bus_priv->common_data.mem_base + offset);
+
+ /* INPUT_IF_CMD */
+ val = (bus_priv->common_data.fs_sync_enable << 5) |
+ (bus_priv->common_data.go_cmd_sel << 4);
+ offset = common_reg->input_if_cmd;
+ cam_io_w_mb(val, bus_priv->common_data.mem_base + offset);
+ return 0;
+}
+
+static int cam_vfe_bus_deinit_hw(void *hw_priv,
+ void *deinit_hw_args, uint32_t arg_size)
+{
+ struct cam_vfe_bus_rd_ver1_priv *bus_priv = hw_priv;
+ int rc = 0;
+
+ if (!bus_priv) {
+ CAM_ERR(CAM_ISP, "Error: Invalid args");
+ return -EINVAL;
+ }
+
+ if (bus_priv->error_irq_handle) {
+ rc = cam_irq_controller_unsubscribe_irq(
+ bus_priv->common_data.bus_irq_controller,
+ bus_priv->error_irq_handle);
+ if (rc)
+ CAM_ERR(CAM_ISP,
+ "Failed to unsubscribe error irq rc=%d", rc);
+
+ bus_priv->error_irq_handle = 0;
+ }
+
+ if (bus_priv->irq_handle) {
+ rc = cam_irq_controller_unsubscribe_irq(
+ bus_priv->common_data.vfe_irq_controller,
+ bus_priv->irq_handle);
+ if (rc)
+ CAM_ERR(CAM_ISP,
+ "Failed to unsubscribe irq rc=%d", rc);
+
+ bus_priv->irq_handle = 0;
+ }
+
+ return rc;
+}
+
+static int __cam_vfe_bus_process_cmd(void *priv,
+ uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
+{
+ return cam_vfe_bus_process_cmd(priv, cmd_type, cmd_args, arg_size);
+}
+
+static int cam_vfe_bus_process_cmd(
+ struct cam_isp_resource_node *priv,
+ uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
+{
+ int rc = -EINVAL;
+
+ if (!priv || !cmd_args) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid input arguments");
+ return -EINVAL;
+ }
+
+ switch (cmd_type) {
+ case CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM:
+ rc = cam_vfe_bus_rd_update_rm(priv, cmd_args, arg_size);
+ break;
+ case CAM_ISP_HW_CMD_GET_HFR_UPDATE_RM:
+ rc = cam_vfe_bus_rd_update_hfr(priv, cmd_args, arg_size);
+ break;
+ case CAM_ISP_HW_CMD_GET_SECURE_MODE:
+ rc = cam_vfe_bus_rd_get_secure_mode(priv, cmd_args, arg_size);
+ break;
+ case CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD:
+ rc = cam_vfe_bus_rd_update_fs_cfg(priv, cmd_args, arg_size);
+ break;
+ default:
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d",
+ cmd_type);
+ break;
+ }
+
+ return rc;
+}
+
+int cam_vfe_bus_rd_ver1_init(
+ struct cam_hw_soc_info *soc_info,
+ struct cam_hw_intf *hw_intf,
+ void *bus_hw_info,
+ void *vfe_irq_controller,
+ struct cam_vfe_bus **vfe_bus)
+{
+ int i, rc = 0;
+ struct cam_vfe_bus_rd_ver1_priv *bus_priv = NULL;
+ struct cam_vfe_bus *vfe_bus_local;
+ struct cam_vfe_bus_rd_ver1_hw_info *bus_rd_hw_info = bus_hw_info;
+
+ if (!soc_info || !hw_intf || !bus_hw_info || !vfe_irq_controller) {
+ CAM_ERR(CAM_ISP,
+ "Inval_prms soc_info:%pK hw_intf:%pK hw_info%pK",
+ soc_info, hw_intf, bus_rd_hw_info);
+ CAM_ERR(CAM_ISP, "controller: %pK", vfe_irq_controller);
+ rc = -EINVAL;
+ goto end;
+ }
+
+ vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
+ if (!vfe_bus_local) {
+ CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus");
+ rc = -ENOMEM;
+ goto end;
+ }
+
+ bus_priv = kzalloc(sizeof(struct cam_vfe_bus_rd_ver1_priv),
+ GFP_KERNEL);
+ if (!bus_priv) {
+ CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus_priv");
+ rc = -ENOMEM;
+ goto free_bus_local;
+ }
+
+ vfe_bus_local->bus_priv = bus_priv;
+
+ bus_priv->num_client = bus_rd_hw_info->num_client;
+ bus_priv->num_bus_rd_resc =
+ bus_rd_hw_info->num_bus_rd_resc;
+ bus_priv->common_data.num_sec_out = 0;
+ bus_priv->common_data.secure_mode = CAM_SECURE_MODE_NON_SECURE;
+ bus_priv->common_data.core_index = soc_info->index;
+ bus_priv->common_data.mem_base =
+ CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX);
+ bus_priv->common_data.hw_intf = hw_intf;
+ bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
+ bus_priv->common_data.common_reg = &bus_rd_hw_info->common_reg;
+
+ mutex_init(&bus_priv->common_data.bus_mutex);
+
+ rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base,
+ &bus_rd_hw_info->common_reg.irq_reg_info,
+ &bus_priv->common_data.bus_irq_controller);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "cam_irq_controller_init failed");
+ goto free_bus_priv;
+ }
+
+ for (i = 0; i < bus_priv->num_client; i++) {
+ rc = cam_vfe_bus_init_rm_resource(i, bus_priv, bus_hw_info,
+ &bus_priv->bus_client[i]);
+ if (rc < 0) {
+ CAM_ERR(CAM_ISP, "Init RM failed rc=%d", rc);
+ goto deinit_rm;
+ }
+ }
+
+ for (i = 0; i < bus_priv->num_bus_rd_resc; i++) {
+ rc = cam_vfe_bus_init_vfe_bus_read_resource(i, bus_priv,
+ bus_rd_hw_info);
+ if (rc < 0) {
+ CAM_ERR(CAM_ISP, "Init VFE Out failed rc=%d", rc);
+ goto deinit_vfe_bus_rd;
+ }
+ }
+
+ spin_lock_init(&bus_priv->common_data.spin_lock);
+
+ vfe_bus_local->hw_ops.reserve = cam_vfe_bus_acquire_vfe_bus_rd;
+ vfe_bus_local->hw_ops.release = cam_vfe_bus_release_vfe_bus_rd;
+ vfe_bus_local->hw_ops.start = cam_vfe_bus_start_hw;
+ vfe_bus_local->hw_ops.stop = cam_vfe_bus_stop_hw;
+ vfe_bus_local->hw_ops.init = cam_vfe_bus_init_hw;
+ vfe_bus_local->hw_ops.deinit = cam_vfe_bus_deinit_hw;
+ vfe_bus_local->top_half_handler = cam_vfe_bus_rd_ver1_handle_irq;
+ vfe_bus_local->bottom_half_handler = NULL;
+ vfe_bus_local->hw_ops.process_cmd = __cam_vfe_bus_process_cmd;
+
+ *vfe_bus = vfe_bus_local;
+
+ return rc;
+
+deinit_vfe_bus_rd:
+ if (i < 0)
+ i = CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX;
+ for (--i; i >= 0; i--)
+ cam_vfe_bus_deinit_vfe_bus_rd_resource(
+ &bus_priv->vfe_bus_rd[i]);
+deinit_rm:
+ if (i < 0)
+ i = bus_priv->num_client;
+ for (--i; i >= 0; i--)
+ cam_vfe_bus_deinit_rm_resource(&bus_priv->bus_client[i]);
+
+free_bus_priv:
+ kfree(vfe_bus_local->bus_priv);
+
+free_bus_local:
+ kfree(vfe_bus_local);
+
+end:
+ return rc;
+}
+
+int cam_vfe_bus_rd_bus_ver1_deinit(
+ struct cam_vfe_bus **vfe_bus)
+{
+ int i, rc = 0;
+ struct cam_vfe_bus_rd_ver1_priv *bus_priv = NULL;
+ struct cam_vfe_bus *vfe_bus_local;
+
+ if (!vfe_bus || !*vfe_bus) {
+ CAM_ERR(CAM_ISP, "Invalid input");
+ return -EINVAL;
+ }
+ vfe_bus_local = *vfe_bus;
+
+ bus_priv = vfe_bus_local->bus_priv;
+ if (!bus_priv) {
+ CAM_ERR(CAM_ISP, "bus_priv is NULL");
+ rc = -ENODEV;
+ goto free_bus_local;
+ }
+
+ for (i = 0; i < bus_priv->num_client; i++) {
+ rc = cam_vfe_bus_deinit_rm_resource(&bus_priv->bus_client[i]);
+ if (rc < 0)
+ CAM_ERR(CAM_ISP,
+ "Deinit RM failed rc=%d", rc);
+ }
+ for (i = 0; i < CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX; i++) {
+ rc = cam_vfe_bus_deinit_vfe_bus_rd_resource(
+ &bus_priv->vfe_bus_rd[i]);
+ if (rc < 0)
+ CAM_ERR(CAM_ISP,
+ "Deinit VFE Out failed rc=%d", rc);
+ }
+
+ rc = cam_irq_controller_deinit(
+ &bus_priv->common_data.bus_irq_controller);
+ if (rc)
+ CAM_ERR(CAM_ISP,
+ "Deinit IRQ Controller failed rc=%d", rc);
+
+ mutex_destroy(&bus_priv->common_data.bus_mutex);
+ kfree(vfe_bus_local->bus_priv);
+
+free_bus_local:
+ kfree(vfe_bus_local);
+
+ *vfe_bus = NULL;
+
+ return rc;
+}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h
new file mode 100644
index 000000000000..9ab2911d6472
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h
@@ -0,0 +1,143 @@
+/* Copyright (c) 2018, 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CAM_VFE_BUS_R_VER1_H_
+#define _CAM_VFE_BUS_R_VER1_H_
+
+#include "cam_irq_controller.h"
+#include "cam_vfe_bus.h"
+
+#define CAM_VFE_BUS_RD_VER1_MAX_CLIENTS 1
+
+enum cam_vfe_bus_rd_ver1_vfe_core_id {
+ CAM_VFE_BUS_RD_VER1_VFE_CORE_0,
+ CAM_VFE_BUS_RD_VER1_VFE_CORE_1,
+ CAM_VFE_BUS_RD_VER1_VFE_CORE_MAX,
+};
+
+enum cam_vfe_bus_rd_ver1_comp_grp_type {
+ CAM_VFE_BUS_RD_VER1_COMP_GRP_0,
+ CAM_VFE_BUS_RD_VER1_COMP_GRP_MAX,
+};
+
+
+enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type {
+ CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0,
+ CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX,
+};
+
+/*
+ * struct cam_vfe_bus_rd_ver1_reg_offset_common:
+ *
+ * @Brief: Common registers across all BUS Clients
+ */
+struct cam_vfe_bus_rd_ver1_reg_offset_common {
+ uint32_t hw_version;
+ uint32_t hw_capability;
+ uint32_t sw_reset;
+ uint32_t cgc_ovd;
+ uint32_t pwr_iso_cfg;
+ uint32_t input_if_cmd;
+ uint32_t test_bus_ctrl;
+ struct cam_irq_controller_reg_info irq_reg_info;
+};
+
+/*
+ * struct cam_vfe_bus_rd_ver1_reg_offset_bus_client:
+ *
+ * @Brief: Register offsets for BUS Clients
+ */
+struct cam_vfe_bus_rd_ver1_reg_offset_bus_client {
+ uint32_t status0;
+ uint32_t status1;
+ uint32_t cfg;
+ uint32_t header_addr;
+ uint32_t header_cfg;
+ uint32_t image_addr;
+ uint32_t image_addr_offset;
+ uint32_t buffer_width_cfg;
+ uint32_t buffer_height_cfg;
+ uint32_t unpacker_cfg;
+ uint32_t stride;
+ void *ubwc_regs;
+ uint32_t burst_limit;
+ uint32_t latency_buf_allocation;
+ uint32_t buf_size;
+};
+
+/*
+ * struct cam_vfe_bus_rd_ver1_vfe_bus_hw_info:
+ *
+ * @Brief: HW capability of VFE Bus Client
+ */
+struct cam_vfe_bus_rd_ver1_vfe_bus_hw_info {
+ enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type vfe_bus_rd_type;
+ uint32_t max_width;
+ uint32_t max_height;
+};
+
+/*
+ * struct cam_vfe_bus_rd_ver1_hw_info:
+ *
+ * @Brief: HW register info for entire Bus
+ *
+ * @common_reg: Common register details
+ * @bus_client_reg: Bus client register info
+ * @comp_reg_grp: Composite group register info
+ * @vfe_out_hw_info: VFE output capability
+ */
+struct cam_vfe_bus_rd_ver1_hw_info {
+ struct cam_vfe_bus_rd_ver1_reg_offset_common common_reg;
+ uint32_t num_client;
+ struct cam_vfe_bus_rd_ver1_reg_offset_bus_client
+ bus_client_reg[CAM_VFE_BUS_RD_VER1_MAX_CLIENTS];
+ uint32_t num_bus_rd_resc;
+ struct cam_vfe_bus_rd_ver1_vfe_bus_hw_info
+ vfe_bus_rd_hw_info[CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX];
+};
+
+/*
+ * cam_vfe_bus_rd_ver1_init()
+ *
+ * @Brief: Initialize Bus layer
+ *
+ * @soc_info: Soc Information for the associated HW
+ * @hw_intf: HW Interface of HW to which this resource belongs
+ * @bus_hw_info: BUS HW info that contains details of BUS registers
+ * @vfe_irq_controller: VFE IRQ Controller to use for subscribing to Top
+ * level IRQs
+ * @vfe_bus: Pointer to vfe_bus structure which will be filled
+ * and returned on successful initialize
+ *
+ * @Return: 0: Success
+ * Non-zero: Failure
+ */
+int cam_vfe_bus_rd_ver1_init(
+ struct cam_hw_soc_info *soc_info,
+ struct cam_hw_intf *hw_intf,
+ void *bus_hw_info,
+ void *vfe_irq_controller,
+ struct cam_vfe_bus **vfe_bus);
+
+/*
+ * cam_vfe_bus_rd_bus_ver1_deinit()
+ *
+ * @Brief: Deinitialize Bus layer
+ *
+ * @vfe_bus: Pointer to vfe_bus structure to deinitialize
+ *
+ * @Return: 0: Success
+ * Non-zero: Failure
+ */
+int cam_vfe_bus_rd_bus_ver1_deinit(struct cam_vfe_bus **vfe_bus);
+
+#endif /* _CAM_VFE_BUS_R_VER1_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
index 7ee9f000a8c0..71285997fb4d 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, 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
@@ -3268,24 +3268,27 @@ static int cam_vfe_bus_init_hw(void *hw_priv,
NULL,
NULL);
- if (bus_priv->irq_handle <= 0) {
+ if ((int)bus_priv->irq_handle <= 0) {
CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ");
return -EFAULT;
}
- bus_priv->error_irq_handle = cam_irq_controller_subscribe_irq(
- bus_priv->common_data.bus_irq_controller,
- CAM_IRQ_PRIORITY_0,
- bus_error_irq_mask,
- bus_priv,
- cam_vfe_bus_error_irq_top_half,
- cam_vfe_bus_err_bottom_half,
- bus_priv->tasklet_info,
- &tasklet_bh_api);
-
- if (bus_priv->irq_handle <= 0) {
- CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ");
- return -EFAULT;
+ if (bus_priv->tasklet_info != NULL) {
+ bus_priv->error_irq_handle = cam_irq_controller_subscribe_irq(
+ bus_priv->common_data.bus_irq_controller,
+ CAM_IRQ_PRIORITY_0,
+ bus_error_irq_mask,
+ bus_priv,
+ cam_vfe_bus_error_irq_top_half,
+ cam_vfe_bus_err_bottom_half,
+ bus_priv->tasklet_info,
+ &tasklet_bh_api);
+
+ if ((int)bus_priv->error_irq_handle <= 0) {
+ CAM_ERR(CAM_ISP, "Failed to subscribe BUS error IRQ %d",
+ bus_priv->error_irq_handle);
+ return -EFAULT;
+ }
}
/*Set Debug Registers*/
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h
index 6f88bc7f5a99..4cdb28a0cb67 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -19,6 +19,7 @@
#define CAM_VFE_BUS_VER_1_0 0x1000
#define CAM_VFE_BUS_VER_2_0 0x2000
+#define CAM_VFE_BUS_RD_VER_4_0 0x4000
enum cam_vfe_bus_plane_type {
PLANE_Y,
@@ -26,6 +27,12 @@ enum cam_vfe_bus_plane_type {
PLANE_MAX,
};
+enum cam_vfe_bus_type {
+ BUS_TYPE_WR,
+ BUS_TYPE_RD,
+ BUS_TYPE_MAX,
+};
+
/*
* struct cam_vfe_bus:
*
@@ -50,6 +57,7 @@ struct cam_vfe_bus {
* @Brief: Initialize Bus layer
*
* @bus_version: Version of BUS to initialize
+ * @bus_type: Bus Type RD/WR
* @soc_info: Soc Information for the associated HW
* @hw_intf: HW Interface of HW to which this resource belongs
* @bus_hw_info: BUS HW info that contains details of BUS registers
@@ -62,6 +70,7 @@ struct cam_vfe_bus {
* Non-zero: Failure
*/
int cam_vfe_bus_init(uint32_t bus_version,
+ int bus_type,
struct cam_hw_soc_info *soc_info,
struct cam_hw_intf *hw_intf,
void *bus_hw_info,
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile
index cdb6b2867433..eb867630d88e 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile
@@ -11,3 +11,4 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vf
obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_camif_lite_ver2.o
obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_top.o cam_vfe_top_ver2.o cam_vfe_camif_ver2.o cam_vfe_rdi.o
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_fe_ver1.o
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c
index 64b77eb7ccb8..b3c795417171 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2019, 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
@@ -166,10 +166,7 @@ static int cam_vfe_camif_lite_resource_start(
static int cam_vfe_camif_lite_resource_stop(
struct cam_isp_resource_node *camif_lite_res)
{
- struct cam_vfe_mux_camif_lite_data *camif_lite_priv;
- struct cam_vfe_camif_lite_ver2_reg *camif_lite_reg;
int rc = 0;
- uint32_t val = 0;
if (!camif_lite_res) {
CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
@@ -180,16 +177,6 @@ static int cam_vfe_camif_lite_resource_stop(
(camif_lite_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE))
return 0;
- camif_lite_priv = (struct cam_vfe_mux_camif_lite_data *)
- camif_lite_res->res_priv;
- camif_lite_reg = camif_lite_priv->camif_lite_reg;
-
- val = cam_io_r_mb(camif_lite_priv->mem_base +
- camif_lite_priv->common_reg->core_cfg);
- val &= (~(1 << camif_lite_priv->reg_data->dual_pd_path_sel_shift));
- cam_io_w_mb(val, camif_lite_priv->mem_base +
- camif_lite_priv->common_reg->core_cfg);
-
if (camif_lite_res->res_state == CAM_ISP_RESOURCE_STATE_STREAMING)
camif_lite_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
index 95bed8d9d23c..c40936525c73 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -212,8 +212,7 @@ static int cam_vfe_camif_resource_start(
uint32_t epoch0_irq_mask;
uint32_t epoch1_irq_mask;
uint32_t computed_epoch_line_cfg;
- uint32_t camera_hw_version = 0;
- int rc = 0;
+ struct cam_vfe_soc_private *soc_private;
if (!camif_res) {
CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
@@ -228,6 +227,13 @@ static int cam_vfe_camif_resource_start(
rsrc_data = (struct cam_vfe_mux_camif_data *)camif_res->res_priv;
+ soc_private = rsrc_data->soc_info->soc_private;
+
+ if (!soc_private) {
+ CAM_ERR(CAM_ISP, "Error! soc_private NULL");
+ return -ENODEV;
+ }
+
/*config vfe core*/
val = (rsrc_data->pix_pattern <<
rsrc_data->reg_data->pixel_pattern_shift);
@@ -253,26 +259,14 @@ static int cam_vfe_camif_resource_start(
rsrc_data->common_reg->module_ctrl[
CAM_VFE_TOP_VER2_MODULE_STATS]->cgc_ovd);
- /* get the HW version */
- rc = cam_cpas_get_cpas_hw_version(&camera_hw_version);
-
- if (rc) {
- CAM_ERR(CAM_ISP, "Couldn't find HW version. rc: %d", rc);
- return rc;
- }
-
/* epoch config */
- switch (camera_hw_version) {
+ switch (soc_private->cpas_version) {
case CAM_CPAS_TITAN_170_V100:
case CAM_CPAS_TITAN_170_V110:
case CAM_CPAS_TITAN_170_V120:
- cam_io_w_mb(rsrc_data->reg_data->epoch_line_cfg,
- rsrc_data->mem_base +
- rsrc_data->camif_reg->epoch_irq);
- break;
default:
- epoch0_irq_mask = ((rsrc_data->last_line -
- rsrc_data->first_line) / 2) +
+ epoch0_irq_mask = (((rsrc_data->last_line -
+ rsrc_data->first_line) * 2) / 3) +
rsrc_data->first_line;
epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg &
0xFFFF;
@@ -316,27 +310,16 @@ static int cam_vfe_camif_resource_start(
}
static int cam_vfe_camif_reg_dump(
- struct cam_isp_resource_node *camif_res)
+ struct cam_vfe_mux_camif_data *camif_priv)
{
- struct cam_vfe_mux_camif_data *camif_priv;
- struct cam_vfe_soc_private *soc_private;
- int rc = 0, i;
- uint32_t val = 0;
+ uint32_t val = 0, wm_idx, offset;
+ int i = 0;
- if (!camif_res) {
- CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
- return -EINVAL;
- }
-
- if ((camif_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) ||
- (camif_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE))
- return 0;
-
- camif_priv = (struct cam_vfe_mux_camif_data *)camif_res->res_priv;
- soc_private = camif_priv->soc_info->soc_private;
- for (i = 0xA3C; i <= 0xA90; i += 4) {
- val = cam_io_r_mb(camif_priv->mem_base + i);
- CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+ for (i = 0xA3C; i <= 0xA90; i += 8) {
+ CAM_INFO(CAM_ISP,
+ "SCALING offset 0x%x val 0x%x offset 0x%x val 0x%x",
+ i, cam_io_r_mb(camif_priv->mem_base + i), i + 4,
+ cam_io_r_mb(camif_priv->mem_base + i + 4));
}
for (i = 0xE0C; i <= 0xE3C; i += 4) {
@@ -344,64 +327,96 @@ static int cam_vfe_camif_reg_dump(
CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
}
- for (i = 0x2000; i <= 0x20B8; i += 4) {
- val = cam_io_r_mb(camif_priv->mem_base + i);
- CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
- }
-
- for (i = 0x2500; i <= 0x255C; i += 4) {
- val = cam_io_r_mb(camif_priv->mem_base + i);
- CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
- }
-
- for (i = 0x2600; i <= 0x265C; i += 4) {
- val = cam_io_r_mb(camif_priv->mem_base + i);
- CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+ for (wm_idx = 0; wm_idx <= 23; wm_idx++) {
+ offset = 0x2214 + 0x100 * wm_idx;
+ CAM_INFO(CAM_ISP,
+ "BUS_WM%u offset 0x%x val 0x%x offset 0x%x val 0x%x",
+ wm_idx, offset,
+ cam_io_r_mb(camif_priv->mem_base + offset),
+ offset + 4, cam_io_r_mb(camif_priv->mem_base +
+ offset + 4));
+ CAM_INFO(CAM_ISP,
+ "offset+8 0x%x val+8 0x%x offset+12 0x%x val+12 0x%x",
+ offset + 8,
+ cam_io_r_mb(camif_priv->mem_base + offset + 8),
+ offset + 12, cam_io_r_mb(camif_priv->mem_base +
+ offset + 12));
}
- cam_cpas_reg_read(soc_private->cpas_handle,
- CAM_CPAS_REG_CAMNOC, 0x420, true, &val);
- CAM_INFO(CAM_ISP, "IFE02_MAXWR_LOW offset 0x420 val 0x%x", val);
+ offset = 0x420;
+ val = cam_soc_util_r(camif_priv->soc_info, 1, offset);
+ CAM_INFO(CAM_ISP, "CAMNOC IFE02 MaxWR_LOW offset 0x%x value 0x%x",
+ offset, val);
- cam_cpas_reg_read(soc_private->cpas_handle,
- CAM_CPAS_REG_CAMNOC, 0x820, true, &val);
- CAM_INFO(CAM_ISP, "IFE13_MAXWR_LOW offset 0x820 val 0x%x", val);
+ offset = 0x820;
+ val = cam_soc_util_r(camif_priv->soc_info, 1, offset);
+ CAM_INFO(CAM_ISP, "CAMNOC IFE13 MaxWR_LOW offset 0x%x value 0x%x",
+ offset, val);
- return rc;
+ return 0;
}
-static int cam_vfe_camif_reg_dump_bh(struct cam_vfe_mux_camif_data *camif_priv)
+static int cam_vfe_camif_reg_dump_bh(
+ struct cam_isp_resource_node *camif_res)
{
+ struct cam_vfe_mux_camif_data *camif_priv;
+ struct cam_vfe_soc_private *soc_private;
uint32_t offset, val, wm_idx;
+ if (!camif_res) {
+ CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
+ return -EINVAL;
+ }
+
+ if ((camif_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) ||
+ (camif_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE))
+ return 0;
+
+ camif_priv = (struct cam_vfe_mux_camif_data *)camif_res->res_priv;
for (offset = 0x0; offset < 0x1000; offset += 0x4) {
val = cam_soc_util_r(camif_priv->soc_info, 0, offset);
- CAM_INFO(CAM_ISP, "offset 0x%x value 0x%x", offset, val);
+ CAM_DBG(CAM_ISP, "offset 0x%x value 0x%x", offset, val);
}
for (offset = 0x2000; offset <= 0x20B8; offset += 0x4) {
val = cam_soc_util_r(camif_priv->soc_info, 0, offset);
- CAM_INFO(CAM_ISP, "offset 0x%x value 0x%x", offset, val);
+ CAM_DBG(CAM_ISP, "offset 0x%x value 0x%x", offset, val);
}
for (wm_idx = 0; wm_idx <= 23; wm_idx++) {
for (offset = 0x2200 + 0x100 * wm_idx;
offset < 0x2278 + 0x100 * wm_idx; offset += 0x4) {
val = cam_soc_util_r(camif_priv->soc_info, 0, offset);
- CAM_INFO(CAM_ISP,
+ CAM_DBG(CAM_ISP,
"offset 0x%x value 0x%x", offset, val);
}
}
- offset = 0x420;
- val = cam_soc_util_r(camif_priv->soc_info, 1, offset);
- CAM_INFO(CAM_ISP, "CAMNOC IFE02 MaxWR_LOW offset 0x%x value 0x%x",
- offset, val);
-
- offset = 0x820;
- val = cam_soc_util_r(camif_priv->soc_info, 1, offset);
- CAM_INFO(CAM_ISP, "CAMNOC IFE13 MaxWR_LOW offset 0x%x value 0x%x",
- offset, val);
+ soc_private = camif_priv->soc_info->soc_private;
+ if (soc_private->cpas_version == CAM_CPAS_TITAN_175_V120) {
+ cam_cpas_reg_read(soc_private->cpas_handle[0],
+ CAM_CPAS_REG_CAMNOC, 0x3A20, true, &val);
+ CAM_DBG(CAM_ISP, "IFE0_nRDI_MAXWR_LOW offset 0x3A20 val 0x%x",
+ val);
+
+ cam_cpas_reg_read(soc_private->cpas_handle[0],
+ CAM_CPAS_REG_CAMNOC, 0x5420, true, &val);
+ CAM_DBG(CAM_ISP, "IFE1_nRDI_MAXWR_LOW offset 0x5420 val 0x%x",
+ val);
+
+ cam_cpas_reg_read(soc_private->cpas_handle[1],
+ CAM_CPAS_REG_CAMNOC, 0x3620, true, &val);
+ CAM_DBG(CAM_ISP,
+ "IFE0123_RDI_WR_MAXWR_LOW offset 0x3620 val 0x%x", val);
+ } else {
+ cam_cpas_reg_read(soc_private->cpas_handle[0],
+ CAM_CPAS_REG_CAMNOC, 0x420, true, &val);
+ CAM_DBG(CAM_ISP, "IFE02_MAXWR_LOW offset 0x420 val 0x%x", val);
+
+ cam_cpas_reg_read(soc_private->cpas_handle[0],
+ CAM_CPAS_REG_CAMNOC, 0x820, true, &val);
+ CAM_DBG(CAM_ISP, "IFE13_MAXWR_LOW offset 0x820 val 0x%x", val);
+ }
return 0;
}
@@ -483,7 +498,7 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node,
arg_size);
break;
case CAM_ISP_HW_CMD_GET_REG_DUMP:
- rc = cam_vfe_camif_reg_dump(rsrc_node);
+ rc = cam_vfe_camif_reg_dump_bh(rsrc_node);
break;
case CAM_ISP_HW_CMD_SOF_IRQ_DEBUG:
rc = cam_vfe_camif_sof_irq_debug(rsrc_node, cmd_args);
@@ -573,11 +588,11 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv,
}
break;
case CAM_ISP_HW_EVENT_ERROR:
- if (irq_status1 & camif_priv->reg_data->error_irq_mask1) {
+ if (irq_status1 & camif_priv->reg_data->error_irq_mask1 &&
+ payload->enable_reg_dump) {
CAM_DBG(CAM_ISP, "Received ERROR\n");
ret = CAM_ISP_HW_ERROR_OVERFLOW;
- cam_vfe_camif_reg_dump(camif_node);
- cam_vfe_camif_reg_dump_bh(camif_node->res_priv);
+ cam_vfe_camif_reg_dump(camif_node->res_priv);
} else {
ret = CAM_ISP_HW_ERROR_NONE;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c
new file mode 100644
index 000000000000..2432d7a5044b
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c
@@ -0,0 +1,638 @@
+/* Copyright (c) 2018, 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include <uapi/media/cam_isp.h>
+#include "cam_io_util.h"
+#include "cam_isp_hw_mgr_intf.h"
+#include "cam_isp_hw.h"
+#include "cam_vfe_hw_intf.h"
+#include "cam_vfe_soc.h"
+#include "cam_vfe_top.h"
+#include "cam_vfe_top_ver2.h"
+#include "cam_vfe_fe_ver1.h"
+#include "cam_debug_util.h"
+#include "cam_cdm_util.h"
+#include "cam_cpas_api.h"
+
+#define CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX 2
+
+struct cam_vfe_mux_fe_data {
+ void __iomem *mem_base;
+ struct cam_hw_intf *hw_intf;
+ struct cam_vfe_fe_ver1_reg *fe_reg;
+ struct cam_vfe_top_ver2_reg_offset_common *common_reg;
+ struct cam_vfe_fe_reg_data *reg_data;
+ struct cam_hw_soc_info *soc_info;
+
+ enum cam_isp_hw_sync_mode sync_mode;
+ uint32_t dsp_mode;
+ uint32_t pix_pattern;
+ uint32_t first_pixel;
+ uint32_t first_line;
+ uint32_t last_pixel;
+ uint32_t last_line;
+ bool enable_sof_irq_debug;
+ uint32_t irq_debug_cnt;
+ uint32_t fe_cfg_data;
+ uint32_t hbi_count;
+};
+
+static int cam_vfe_fe_validate_pix_pattern(uint32_t pattern)
+{
+ int rc;
+
+ switch (pattern) {
+ case CAM_ISP_PATTERN_BAYER_RGRGRG:
+ case CAM_ISP_PATTERN_BAYER_GRGRGR:
+ case CAM_ISP_PATTERN_BAYER_BGBGBG:
+ case CAM_ISP_PATTERN_BAYER_GBGBGB:
+ case CAM_ISP_PATTERN_YUV_YCBYCR:
+ case CAM_ISP_PATTERN_YUV_YCRYCB:
+ case CAM_ISP_PATTERN_YUV_CBYCRY:
+ case CAM_ISP_PATTERN_YUV_CRYCBY:
+ rc = 0;
+ break;
+ default:
+ CAM_ERR(CAM_ISP, "Error! Invalid pix pattern:%d", pattern);
+ rc = -EINVAL;
+ break;
+ }
+ return rc;
+}
+
+static int cam_vfe_fe_update(
+ struct cam_isp_resource_node *fe_res,
+ void *cmd_data, uint32_t arg_size)
+{
+ struct cam_vfe_mux_fe_data *rsrc_data = NULL;
+ struct cam_vfe_fe_update_args *args = cmd_data;
+ uint32_t fe_cfg_data;
+
+ if (arg_size != sizeof(struct cam_vfe_fe_update_args)) {
+ CAM_ERR(CAM_ISP, "Invalid cmd size");
+ return -EINVAL;
+ }
+
+ if (!args) {
+ CAM_ERR(CAM_ISP, "Invalid args");
+ return -EINVAL;
+ }
+
+ CAM_DBG(CAM_ISP, "fe_update->min_vbi = 0x%x", args->fe_config.min_vbi);
+ CAM_DBG(CAM_ISP, "fe_update->hbi_count = 0x%x",
+ args->fe_config.hbi_count);
+ CAM_DBG(CAM_ISP, "fe_update->fs_mode = 0x%x", args->fe_config.fs_mode);
+ CAM_DBG(CAM_ISP, "fe_update->fs_line_sync_en = 0x%x",
+ args->fe_config.fs_line_sync_en);
+
+ fe_cfg_data = args->fe_config.min_vbi |
+ args->fe_config.fs_mode << 8 |
+ args->fe_config.fs_line_sync_en;
+
+ rsrc_data = fe_res->res_priv;
+ rsrc_data->fe_cfg_data = fe_cfg_data;
+ rsrc_data->hbi_count = args->fe_config.hbi_count;
+
+ CAM_DBG(CAM_ISP, "fe_cfg_data = 0x%x", fe_cfg_data);
+ return 0;
+}
+
+static int cam_vfe_fe_get_reg_update(
+ struct cam_isp_resource_node *fe_res,
+ void *cmd_args, uint32_t arg_size)
+{
+ uint32_t size = 0;
+ uint32_t reg_val_pair[2];
+ struct cam_isp_hw_get_cmd_update *cdm_args = cmd_args;
+ struct cam_cdm_utils_ops *cdm_util_ops = NULL;
+ struct cam_vfe_mux_fe_data *rsrc_data = NULL;
+
+ if (arg_size != sizeof(struct cam_isp_hw_get_cmd_update)) {
+ CAM_ERR(CAM_ISP, "Invalid cmd size");
+ return -EINVAL;
+ }
+
+ if (!cdm_args || !cdm_args->res) {
+ CAM_ERR(CAM_ISP, "Invalid args");
+ return -EINVAL;
+ }
+
+ cdm_util_ops = (struct cam_cdm_utils_ops *)cdm_args->res->cdm_ops;
+
+ if (!cdm_util_ops) {
+ CAM_ERR(CAM_ISP, "Invalid CDM ops");
+ return -EINVAL;
+ }
+
+ if (cdm_args->rup_data->is_fe_enable &&
+ (cdm_args->rup_data->res_bitmap &
+ (1 << CAM_IFE_REG_UPD_CMD_RDI1_BIT))) {
+ CAM_DBG(CAM_ISP, "Avoiding rup_upd for fe");
+ cdm_args->cmd.used_bytes = 0;
+ return 0;
+ }
+
+ size = cdm_util_ops->cdm_required_size_reg_random(1);
+ /* since cdm returns dwords, we need to convert it into bytes */
+ if ((size * 4) > cdm_args->cmd.size) {
+ CAM_ERR(CAM_ISP, "buf size:%d is not sufficient, expected: %d",
+ cdm_args->cmd.size, size);
+ return -EINVAL;
+ }
+
+ rsrc_data = fe_res->res_priv;
+ reg_val_pair[0] = rsrc_data->fe_reg->reg_update_cmd;
+ reg_val_pair[1] = rsrc_data->reg_data->reg_update_cmd_data;
+ CAM_DBG(CAM_ISP, "CAMIF res_id %d reg_update_cmd 0x%x offset 0x%x",
+ fe_res->res_id, reg_val_pair[1], reg_val_pair[0]);
+
+ cdm_util_ops->cdm_write_regrandom(cdm_args->cmd.cmd_buf_addr,
+ 1, reg_val_pair);
+
+ cdm_args->cmd.used_bytes = size * 4;
+
+ return 0;
+}
+
+int cam_vfe_fe_ver1_acquire_resource(
+ struct cam_isp_resource_node *fe_res,
+ void *acquire_param)
+{
+ struct cam_vfe_mux_fe_data *fe_data;
+ struct cam_vfe_acquire_args *acquire_data;
+
+ int rc = 0;
+
+ fe_data = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+ acquire_data = (struct cam_vfe_acquire_args *)acquire_param;
+
+ rc = cam_vfe_fe_validate_pix_pattern(
+ acquire_data->vfe_in.in_port->test_pattern);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "pix validation failed: id:%d pix_pattern %d",
+ fe_res->hw_intf->hw_idx,
+ acquire_data->vfe_in.in_port->test_pattern);
+ return rc;
+ }
+
+ fe_data->sync_mode = acquire_data->vfe_in.sync_mode;
+ fe_data->pix_pattern = acquire_data->vfe_in.in_port->test_pattern;
+ fe_data->dsp_mode = acquire_data->vfe_in.in_port->dsp_mode;
+ fe_data->first_pixel = acquire_data->vfe_in.in_port->left_start;
+ fe_data->last_pixel = acquire_data->vfe_in.in_port->left_stop;
+ fe_data->first_line = acquire_data->vfe_in.in_port->line_start;
+ fe_data->last_line = acquire_data->vfe_in.in_port->line_stop;
+
+ CAM_DBG(CAM_ISP, "hw id:%d pix_pattern:%d dsp_mode=%d",
+ fe_res->hw_intf->hw_idx,
+ fe_data->pix_pattern, fe_data->dsp_mode);
+ return rc;
+}
+
+static int cam_vfe_fe_resource_init(
+ struct cam_isp_resource_node *fe_res,
+ void *init_args, uint32_t arg_size)
+{
+ struct cam_vfe_mux_fe_data *fe_data;
+ struct cam_hw_soc_info *soc_info;
+ int rc = 0;
+
+ if (!fe_res) {
+ CAM_ERR(CAM_ISP, "Error Invalid input arguments");
+ return -EINVAL;
+ }
+
+ fe_data = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+
+ soc_info = fe_data->soc_info;
+
+ if ((fe_data->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) &&
+ (fe_data->dsp_mode <= CAM_ISP_DSP_MODE_ROUND)) {
+ rc = cam_vfe_soc_enable_clk(soc_info, CAM_VFE_DSP_CLK_NAME);
+ if (rc)
+ CAM_ERR(CAM_ISP, "failed to enable dsp clk");
+ }
+
+ return rc;
+}
+
+static int cam_vfe_fe_resource_deinit(
+ struct cam_isp_resource_node *fe_res,
+ void *init_args, uint32_t arg_size)
+{
+ struct cam_vfe_mux_fe_data *fe_data;
+ struct cam_hw_soc_info *soc_info;
+ int rc = 0;
+
+ if (!fe_res) {
+ CAM_ERR(CAM_ISP, "Error Invalid input arguments");
+ return -EINVAL;
+ }
+
+ fe_data = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+
+ soc_info = fe_data->soc_info;
+
+ if ((fe_data->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) &&
+ (fe_data->dsp_mode <= CAM_ISP_DSP_MODE_ROUND)) {
+ rc = cam_vfe_soc_disable_clk(soc_info, CAM_VFE_DSP_CLK_NAME);
+ if (rc)
+ CAM_ERR(CAM_ISP, "failed to disable dsp clk");
+ }
+
+ return rc;
+
+}
+
+static int cam_vfe_fe_resource_start(
+ struct cam_isp_resource_node *fe_res)
+{
+ struct cam_vfe_mux_fe_data *rsrc_data;
+ uint32_t val = 0;
+ uint32_t epoch0_irq_mask;
+ uint32_t epoch1_irq_mask;
+ uint32_t computed_epoch_line_cfg;
+
+ if (!fe_res) {
+ CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
+ return -EINVAL;
+ }
+
+ if (fe_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
+ CAM_ERR(CAM_ISP, "Error! Invalid fe res res_state:%d",
+ fe_res->res_state);
+ return -EINVAL;
+ }
+
+ rsrc_data = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+
+ /* config vfe core */
+ val = (rsrc_data->pix_pattern <<
+ rsrc_data->reg_data->pixel_pattern_shift);
+ if (rsrc_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE)
+ val |= (1 << rsrc_data->reg_data->extern_reg_update_shift);
+
+ if ((rsrc_data->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) &&
+ (rsrc_data->dsp_mode <= CAM_ISP_DSP_MODE_ROUND)) {
+ /* DSP mode reg val is CAM_ISP_DSP_MODE - 1 */
+ val |= (((rsrc_data->dsp_mode - 1) &
+ rsrc_data->reg_data->dsp_mode_mask) <<
+ rsrc_data->reg_data->dsp_mode_shift);
+ val |= (0x1 << rsrc_data->reg_data->dsp_en_shift);
+ }
+
+ if (rsrc_data->fe_cfg_data) {
+ /*set Mux mode value to EXT_RD_PATH */
+ val |= (rsrc_data->reg_data->fe_mux_data <<
+ rsrc_data->reg_data->input_mux_sel_shift);
+ }
+
+ if (rsrc_data->hbi_count) {
+ /*set hbi count*/
+ val |= (rsrc_data->hbi_count <<
+ rsrc_data->reg_data->hbi_cnt_shift);
+ }
+ cam_io_w_mb(val, rsrc_data->mem_base + rsrc_data->common_reg->core_cfg);
+
+ CAM_DBG(CAM_ISP, "hw id:%d core_cfg (off:0x%x, val:0x%x)",
+ fe_res->hw_intf->hw_idx,
+ rsrc_data->common_reg->core_cfg,
+ val);
+
+ /* disable the CGC for stats */
+ cam_io_w_mb(0xFFFFFFFF, rsrc_data->mem_base +
+ rsrc_data->common_reg->module_ctrl[
+ CAM_VFE_TOP_VER2_MODULE_STATS]->cgc_ovd);
+
+ /* epoch config */
+ epoch0_irq_mask = ((rsrc_data->last_line - rsrc_data->first_line) / 2) +
+ rsrc_data->first_line;
+
+ epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg & 0xFFFF;
+ computed_epoch_line_cfg = (epoch0_irq_mask << 16) | epoch1_irq_mask;
+ cam_io_w_mb(computed_epoch_line_cfg,
+ rsrc_data->mem_base + rsrc_data->fe_reg->epoch_irq);
+ CAM_DBG(CAM_ISP, "first_line:0x%x last_line:0x%x epoch_line_cfg: 0x%x",
+ rsrc_data->first_line, rsrc_data->last_line,
+ computed_epoch_line_cfg);
+
+ fe_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
+
+ /* Read Back cfg */
+ cam_io_w_mb(rsrc_data->fe_cfg_data,
+ rsrc_data->mem_base + rsrc_data->fe_reg->fe_cfg);
+ CAM_DBG(CAM_ISP, "hw id:%d fe_cfg_data(off:0x%x val:0x%x)",
+ fe_res->hw_intf->hw_idx,
+ rsrc_data->fe_reg->fe_cfg,
+ rsrc_data->fe_cfg_data);
+
+ /* Reg Update */
+ cam_io_w_mb(rsrc_data->reg_data->reg_update_cmd_data,
+ rsrc_data->mem_base + rsrc_data->fe_reg->reg_update_cmd);
+ CAM_DBG(CAM_ISP, "hw id:%d RUP (off:0x%x, val:0x%x)",
+ fe_res->hw_intf->hw_idx,
+ rsrc_data->fe_reg->reg_update_cmd,
+ rsrc_data->reg_data->reg_update_cmd_data);
+
+ /* disable sof irq debug flag */
+ rsrc_data->enable_sof_irq_debug = false;
+ rsrc_data->irq_debug_cnt = 0;
+
+ CAM_DBG(CAM_ISP, "Start Camif IFE %d Done", fe_res->hw_intf->hw_idx);
+ return 0;
+}
+
+static int cam_vfe_fe_reg_dump(
+ struct cam_isp_resource_node *fe_res)
+{
+ struct cam_vfe_mux_fe_data *fe_priv;
+ struct cam_vfe_soc_private *soc_private;
+ int rc = 0, i;
+ uint32_t val = 0;
+
+ if (!fe_res) {
+ CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
+ return -EINVAL;
+ }
+
+ if ((fe_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) ||
+ (fe_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE))
+ return 0;
+
+ fe_priv = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+ soc_private = fe_priv->soc_info->soc_private;
+ for (i = 0xA3C; i <= 0xA90; i += 4) {
+ val = cam_io_r_mb(fe_priv->mem_base + i);
+ CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+ }
+
+ for (i = 0xE0C; i <= 0xE3C; i += 4) {
+ val = cam_io_r_mb(fe_priv->mem_base + i);
+ CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+ }
+
+ for (i = 0x2000; i <= 0x20B8; i += 4) {
+ val = cam_io_r_mb(fe_priv->mem_base + i);
+ CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+ }
+
+ for (i = 0x2500; i <= 0x255C; i += 4) {
+ val = cam_io_r_mb(fe_priv->mem_base + i);
+ CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+ }
+
+ for (i = 0x2600; i <= 0x265C; i += 4) {
+ val = cam_io_r_mb(fe_priv->mem_base + i);
+ CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+ }
+
+ cam_cpas_reg_read((uint32_t)soc_private->cpas_handle[0],
+ CAM_CPAS_REG_CAMNOC, 0x420, true, &val);
+ CAM_INFO(CAM_ISP, "IFE02_MAXWR_LOW offset 0x420 val 0x%x", val);
+
+ cam_cpas_reg_read((uint32_t)soc_private->cpas_handle[0],
+ CAM_CPAS_REG_CAMNOC, 0x820, true, &val);
+ CAM_INFO(CAM_ISP, "IFE13_MAXWR_LOW offset 0x820 val 0x%x", val);
+
+ return rc;
+}
+
+static int cam_vfe_fe_resource_stop(
+ struct cam_isp_resource_node *fe_res)
+{
+ struct cam_vfe_mux_fe_data *fe_priv;
+ struct cam_vfe_fe_ver1_reg *fe_reg;
+ int rc = 0;
+ uint32_t val = 0;
+
+ if (!fe_res) {
+ CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
+ return -EINVAL;
+ }
+
+ if (fe_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED ||
+ fe_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE)
+ return 0;
+
+ fe_priv = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+ fe_reg = fe_priv->fe_reg;
+
+ if ((fe_priv->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) &&
+ (fe_priv->dsp_mode <= CAM_ISP_DSP_MODE_ROUND)) {
+ val = cam_io_r_mb(fe_priv->mem_base +
+ fe_priv->common_reg->core_cfg);
+ val &= (~(1 << fe_priv->reg_data->dsp_en_shift));
+ cam_io_w_mb(val, fe_priv->mem_base +
+ fe_priv->common_reg->core_cfg);
+ }
+
+ if (fe_res->res_state == CAM_ISP_RESOURCE_STATE_STREAMING)
+ fe_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+
+ return rc;
+}
+
+static int cam_vfe_fe_sof_irq_debug(
+ struct cam_isp_resource_node *rsrc_node, void *cmd_args)
+{
+ struct cam_vfe_mux_fe_data *fe_priv;
+ uint32_t *enable_sof_irq = (uint32_t *)cmd_args;
+
+ fe_priv =
+ (struct cam_vfe_mux_fe_data *)rsrc_node->res_priv;
+
+ if (*enable_sof_irq == 1)
+ fe_priv->enable_sof_irq_debug = true;
+ else
+ fe_priv->enable_sof_irq_debug = false;
+
+ return 0;
+}
+
+static int cam_vfe_fe_process_cmd(struct cam_isp_resource_node *rsrc_node,
+ uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
+{
+ int rc = -EINVAL;
+
+ if (!rsrc_node || !cmd_args) {
+ CAM_ERR(CAM_ISP, "Invalid input arguments");
+ return -EINVAL;
+ }
+
+ switch (cmd_type) {
+ case CAM_ISP_HW_CMD_GET_REG_UPDATE:
+ rc = cam_vfe_fe_get_reg_update(rsrc_node, cmd_args,
+ arg_size);
+ break;
+ case CAM_ISP_HW_CMD_GET_REG_DUMP:
+ rc = cam_vfe_fe_reg_dump(rsrc_node);
+ break;
+ case CAM_ISP_HW_CMD_SOF_IRQ_DEBUG:
+ rc = cam_vfe_fe_sof_irq_debug(rsrc_node, cmd_args);
+ break;
+ case CAM_ISP_HW_CMD_FE_UPDATE_IN_RD:
+ rc = cam_vfe_fe_update(rsrc_node, cmd_args, arg_size);
+ break;
+ default:
+ CAM_ERR(CAM_ISP,
+ "unsupported process command:%d", cmd_type);
+ break;
+ }
+
+ return rc;
+}
+
+static int cam_vfe_fe_handle_irq_top_half(uint32_t evt_id,
+ struct cam_irq_th_payload *th_payload)
+{
+ return -EPERM;
+}
+
+static int cam_vfe_fe_handle_irq_bottom_half(void *handler_priv,
+ void *evt_payload_priv)
+{
+ int ret = CAM_VFE_IRQ_STATUS_ERR;
+ struct cam_isp_resource_node *fe_node;
+ struct cam_vfe_mux_fe_data *fe_priv;
+ struct cam_vfe_top_irq_evt_payload *payload;
+ uint32_t irq_status0;
+ uint32_t irq_status1;
+
+ if (!handler_priv || !evt_payload_priv) {
+ CAM_ERR(CAM_ISP, "Invalid params");
+ return ret;
+ }
+
+ fe_node = handler_priv;
+ fe_priv = fe_node->res_priv;
+ payload = evt_payload_priv;
+ irq_status0 = payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS0];
+ irq_status1 = payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS1];
+
+ CAM_DBG(CAM_ISP, "event ID:%d, irq_status_0 = 0x%x",
+ payload->evt_id, irq_status0);
+
+ switch (payload->evt_id) {
+ case CAM_ISP_HW_EVENT_SOF:
+ if (irq_status0 & fe_priv->reg_data->sof_irq_mask) {
+ if ((fe_priv->enable_sof_irq_debug) &&
+ (fe_priv->irq_debug_cnt <=
+ CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX)) {
+ CAM_INFO_RATE_LIMIT(CAM_ISP, "Received SOF");
+
+ fe_priv->irq_debug_cnt++;
+ if (fe_priv->irq_debug_cnt ==
+ CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX) {
+ fe_priv->enable_sof_irq_debug =
+ false;
+ fe_priv->irq_debug_cnt = 0;
+ }
+ } else {
+ CAM_DBG(CAM_ISP, "Received SOF");
+ }
+ ret = CAM_VFE_IRQ_STATUS_SUCCESS;
+ }
+ break;
+ case CAM_ISP_HW_EVENT_EPOCH:
+ if (irq_status0 & fe_priv->reg_data->epoch0_irq_mask) {
+ CAM_DBG(CAM_ISP, "Received EPOCH");
+ ret = CAM_VFE_IRQ_STATUS_SUCCESS;
+ }
+ break;
+ case CAM_ISP_HW_EVENT_REG_UPDATE:
+ if (irq_status0 & fe_priv->reg_data->reg_update_irq_mask) {
+ CAM_DBG(CAM_ISP, "Received REG_UPDATE_ACK");
+ ret = CAM_VFE_IRQ_STATUS_SUCCESS;
+ }
+ break;
+ case CAM_ISP_HW_EVENT_EOF:
+ if (irq_status0 & fe_priv->reg_data->eof_irq_mask) {
+ CAM_DBG(CAM_ISP, "Received EOF\n");
+ ret = CAM_VFE_IRQ_STATUS_SUCCESS;
+ }
+ break;
+ case CAM_ISP_HW_EVENT_ERROR:
+ if (irq_status1 & fe_priv->reg_data->error_irq_mask1) {
+ CAM_DBG(CAM_ISP, "Received ERROR\n");
+ ret = CAM_ISP_HW_ERROR_OVERFLOW;
+ cam_vfe_fe_reg_dump(fe_node);
+ } else {
+ ret = CAM_ISP_HW_ERROR_NONE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ CAM_DBG(CAM_ISP, "returing status = %d", ret);
+ return ret;
+}
+
+int cam_vfe_fe_ver1_init(
+ struct cam_hw_intf *hw_intf,
+ struct cam_hw_soc_info *soc_info,
+ void *fe_hw_info,
+ struct cam_isp_resource_node *fe_node)
+{
+ struct cam_vfe_mux_fe_data *fe_priv = NULL;
+ struct cam_vfe_fe_ver1_hw_info *fe_info = fe_hw_info;
+
+ fe_priv = kzalloc(sizeof(struct cam_vfe_mux_fe_data),
+ GFP_KERNEL);
+ if (!fe_priv) {
+ CAM_ERR(CAM_ISP, "Error! Failed to alloc for fe_priv");
+ return -ENOMEM;
+ }
+
+ fe_node->res_priv = fe_priv;
+
+ fe_priv->mem_base = soc_info->reg_map[VFE_CORE_BASE_IDX].mem_base;
+ fe_priv->fe_reg = fe_info->fe_reg;
+ fe_priv->common_reg = fe_info->common_reg;
+ fe_priv->reg_data = fe_info->reg_data;
+ fe_priv->hw_intf = hw_intf;
+ fe_priv->soc_info = soc_info;
+
+ fe_node->init = cam_vfe_fe_resource_init;
+ fe_node->deinit = cam_vfe_fe_resource_deinit;
+ fe_node->start = cam_vfe_fe_resource_start;
+ fe_node->stop = cam_vfe_fe_resource_stop;
+ fe_node->process_cmd = cam_vfe_fe_process_cmd;
+ fe_node->top_half_handler = cam_vfe_fe_handle_irq_top_half;
+ fe_node->bottom_half_handler = cam_vfe_fe_handle_irq_bottom_half;
+
+ return 0;
+}
+
+int cam_vfe_fe_ver1_deinit(
+ struct cam_isp_resource_node *fe_node)
+{
+ struct cam_vfe_mux_fe_data *fe_priv = fe_node->res_priv;
+
+ fe_node->start = NULL;
+ fe_node->stop = NULL;
+ fe_node->process_cmd = NULL;
+ fe_node->top_half_handler = NULL;
+ fe_node->bottom_half_handler = NULL;
+
+ fe_node->res_priv = NULL;
+
+ if (!fe_priv) {
+ CAM_ERR(CAM_ISP, "Error! fe_priv is NULL");
+ return -ENODEV;
+ }
+
+ kfree(fe_priv);
+
+ return 0;
+}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.h
new file mode 100644
index 000000000000..0f8d2f18d1ec
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.h
@@ -0,0 +1,94 @@
+/* Copyright (c) 2018, 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CAM_VFE_FE_VER1_H_
+#define _CAM_VFE_FE_VER1_H_
+
+#include "cam_isp_hw.h"
+#include "cam_vfe_top.h"
+
+struct cam_vfe_fe_ver1_reg {
+ uint32_t camif_cmd;
+ uint32_t camif_config;
+ uint32_t line_skip_pattern;
+ uint32_t pixel_skip_pattern;
+ uint32_t skip_period;
+ uint32_t irq_subsample_pattern;
+ uint32_t epoch_irq;
+ uint32_t raw_crop_width_cfg;
+ uint32_t raw_crop_height_cfg;
+ uint32_t reg_update_cmd;
+ uint32_t vfe_diag_config;
+ uint32_t vfe_diag_sensor_status;
+ uint32_t fe_cfg;
+};
+
+struct cam_vfe_fe_reg_data {
+ uint32_t raw_crop_first_pixel_shift;
+ uint32_t raw_crop_first_pixel_mask;
+
+ uint32_t raw_crop_last_pixel_shift;
+ uint32_t raw_crop_last_pixel_mask;
+
+ uint32_t raw_crop_first_line_shift;
+ uint32_t raw_crop_first_line_mask;
+
+ uint32_t raw_crop_last_line_shift;
+ uint32_t raw_crop_last_line_mask;
+
+ uint32_t input_mux_sel_shift;
+ uint32_t input_mux_sel_mask;
+ uint32_t extern_reg_update_shift;
+ uint32_t extern_reg_update_mask;
+
+ uint32_t pixel_pattern_shift;
+ uint32_t pixel_pattern_mask;
+
+ uint32_t dsp_mode_shift;
+ uint32_t dsp_mode_mask;
+ uint32_t dsp_en_shift;
+ uint32_t dsp_en_mask;
+
+ uint32_t reg_update_cmd_data;
+ uint32_t epoch_line_cfg;
+ uint32_t sof_irq_mask;
+ uint32_t epoch0_irq_mask;
+ uint32_t reg_update_irq_mask;
+ uint32_t eof_irq_mask;
+ uint32_t error_irq_mask0;
+ uint32_t error_irq_mask1;
+
+ uint32_t enable_diagnostic_hw;
+ uint32_t fe_mux_data;
+ uint32_t hbi_cnt_shift;
+};
+
+struct cam_vfe_fe_ver1_hw_info {
+ struct cam_vfe_top_ver2_reg_offset_common *common_reg;
+ struct cam_vfe_fe_ver1_reg *fe_reg;
+ struct cam_vfe_fe_reg_data *reg_data;
+};
+
+int cam_vfe_fe_ver1_acquire_resource(
+ struct cam_isp_resource_node *camif_res,
+ void *acquire_param);
+
+int cam_vfe_fe_ver1_init(
+ struct cam_hw_intf *hw_intf,
+ struct cam_hw_soc_info *soc_info,
+ void *camif_hw_info,
+ struct cam_isp_resource_node *camif_node);
+
+int cam_vfe_fe_ver1_deinit(
+ struct cam_isp_resource_node *camif_node);
+
+#endif /* _CAM_VFE_FE_VER1_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c
index 230698f7f890..c2c1bc20463b 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -64,6 +64,14 @@ static int cam_vfe_rdi_get_reg_update(
return -EINVAL;
}
+ if (cdm_args->rup_data->is_fe_enable &&
+ (cdm_args->rup_data->res_bitmap &
+ (1 << CAM_IFE_REG_UPD_CMD_PIX_BIT))) {
+ cdm_args->cmd.used_bytes = 0;
+ CAM_DBG(CAM_ISP, "Avoiding reg_upd for fe for rdi");
+ return 0;
+ }
+
rsrc_data = rdi_res->res_priv;
reg_val_pair[0] = rsrc_data->rdi_reg->reg_update_cmd;
reg_val_pair[1] = rsrc_data->reg_data->reg_update_cmd_data;
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
index f54f52af5334..569bbb6b2ce0 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -37,11 +37,13 @@ struct cam_vfe_top_ver2_priv {
struct cam_axi_vote applied_axi_vote;
struct cam_axi_vote req_axi_vote[CAM_VFE_TOP_VER2_MUX_MAX];
unsigned long req_clk_rate[CAM_VFE_TOP_VER2_MUX_MAX];
- struct cam_axi_vote last_vote[CAM_VFE_TOP_VER2_MUX_MAX *
+ struct cam_axi_vote last_vote[CAM_CPAS_HANDLE_MAX]
+ [CAM_VFE_TOP_VER2_MUX_MAX *
CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES];
- uint32_t last_counter;
+ uint32_t last_counter[CAM_CPAS_HANDLE_MAX];
enum cam_vfe_bw_control_action
axi_vote_control[CAM_VFE_TOP_VER2_MUX_MAX];
+ enum cam_cpas_handle_id cpashdl_type[CAM_VFE_TOP_VER2_MUX_MAX];
};
static int cam_vfe_top_mux_get_base(struct cam_vfe_top_ver2_priv *top_priv,
@@ -133,99 +135,131 @@ static int cam_vfe_top_set_axi_bw_vote(
struct cam_vfe_soc_private *soc_private =
soc_info->soc_private;
bool apply_bw_update = false;
+ enum cam_cpas_handle_id cpashdl_type;
+ struct cam_axi_vote *last_vote = NULL;
if (!soc_private) {
CAM_ERR(CAM_ISP, "Error soc_private NULL");
return -EINVAL;
}
- for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) {
- if (top_priv->axi_vote_control[i] ==
- CAM_VFE_BW_CONTROL_INCLUDE) {
- sum.uncompressed_bw +=
+ for (cpashdl_type = 0; cpashdl_type < CAM_CPAS_HANDLE_MAX;
+ cpashdl_type++) {
+
+ if ((soc_private->cpas_version != CAM_CPAS_TITAN_175_V120)
+ && cpashdl_type)
+ continue;
+
+ sum.uncompressed_bw = sum.compressed_bw = 0;
+ to_be_applied_axi_vote.uncompressed_bw = 0;
+ to_be_applied_axi_vote.compressed_bw = 0;
+ apply_bw_update = false;
+
+ for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) {
+ if (top_priv->axi_vote_control[i] ==
+ CAM_VFE_BW_CONTROL_INCLUDE &&
+ top_priv->cpashdl_type[i] ==
+ cpashdl_type) {
+ sum.uncompressed_bw +=
top_priv->req_axi_vote[i].uncompressed_bw;
- sum.compressed_bw +=
+ sum.compressed_bw +=
top_priv->req_axi_vote[i].compressed_bw;
+ }
}
- }
-
- CAM_DBG(CAM_ISP, "Updating BW from (%llu %llu) to (%llu %llu)",
- top_priv->applied_axi_vote.uncompressed_bw,
- top_priv->applied_axi_vote.compressed_bw,
- sum.uncompressed_bw,
- sum.compressed_bw);
- top_priv->last_vote[top_priv->last_counter] = sum;
- top_priv->last_counter = (top_priv->last_counter + 1) %
- (CAM_VFE_TOP_VER2_MUX_MAX *
- CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES);
-
- if ((top_priv->applied_axi_vote.uncompressed_bw ==
- sum.uncompressed_bw) &&
- (top_priv->applied_axi_vote.compressed_bw ==
- sum.compressed_bw)) {
- CAM_DBG(CAM_ISP, "BW config unchanged %llu %llu",
+ CAM_DBG(CAM_ISP, "Updating BW from (%llu %llu) to (%llu %llu)",
top_priv->applied_axi_vote.uncompressed_bw,
- top_priv->applied_axi_vote.compressed_bw);
- return 0;
- }
+ top_priv->applied_axi_vote.compressed_bw,
+ sum.uncompressed_bw,
+ sum.compressed_bw);
- if (start_stop == true) {
- /* need to vote current request immediately */
- to_be_applied_axi_vote = sum;
- /* Reset everything, we can start afresh */
- memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) *
- (CAM_VFE_TOP_VER2_MUX_MAX *
- CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES));
- top_priv->last_counter = 0;
- top_priv->last_vote[top_priv->last_counter] = sum;
- top_priv->last_counter = (top_priv->last_counter + 1) %
+ last_vote = top_priv->last_vote[cpashdl_type];
+
+ last_vote[top_priv->last_counter[cpashdl_type]] = sum;
+ top_priv->last_counter[cpashdl_type] =
+ (top_priv->last_counter[cpashdl_type] + 1) %
(CAM_VFE_TOP_VER2_MUX_MAX *
CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES);
- } else {
+
+ if ((top_priv->applied_axi_vote.uncompressed_bw ==
+ sum.uncompressed_bw) &&
+ (top_priv->applied_axi_vote.compressed_bw ==
+ sum.compressed_bw)) {
+ CAM_DBG(CAM_ISP, "BW config unchanged %llu %llu",
+ top_priv->applied_axi_vote.uncompressed_bw,
+ top_priv->applied_axi_vote.compressed_bw);
+ return 0;
+ }
+
+ if (start_stop == true) {
+ rc = cam_cpas_update_axi_vote(
+ soc_private->cpas_handle[cpashdl_type],
+ &to_be_applied_axi_vote);
+ if (!rc) {
+ top_priv->applied_axi_vote.uncompressed_bw =
+ to_be_applied_axi_vote.uncompressed_bw;
+ top_priv->applied_axi_vote.compressed_bw =
+ to_be_applied_axi_vote.compressed_bw;
+ }
+ return rc;
+ }
+
/*
- * Find max bw request in last few frames. This will the bw
- *that we want to vote to CPAS now.
+ * Find max bw request in last few frames. This is the bw
+ * that we want to vote to CPAS now.
*/
for (i = 0; i < (CAM_VFE_TOP_VER2_MUX_MAX *
CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); i++) {
if (to_be_applied_axi_vote.compressed_bw <
- top_priv->last_vote[i].compressed_bw)
+ last_vote[i].compressed_bw)
to_be_applied_axi_vote.compressed_bw =
- top_priv->last_vote[i].compressed_bw;
+ last_vote[i].compressed_bw;
if (to_be_applied_axi_vote.uncompressed_bw <
- top_priv->last_vote[i].uncompressed_bw)
+ last_vote[i].uncompressed_bw)
to_be_applied_axi_vote.uncompressed_bw =
- top_priv->last_vote[i].uncompressed_bw;
+ last_vote[i].uncompressed_bw;
}
- }
- if ((to_be_applied_axi_vote.uncompressed_bw !=
- top_priv->applied_axi_vote.uncompressed_bw) ||
- (to_be_applied_axi_vote.compressed_bw !=
- top_priv->applied_axi_vote.compressed_bw))
- apply_bw_update = true;
+ if ((to_be_applied_axi_vote.uncompressed_bw !=
+ top_priv->applied_axi_vote.uncompressed_bw) ||
+ (to_be_applied_axi_vote.compressed_bw !=
+ top_priv->applied_axi_vote.compressed_bw))
+ apply_bw_update = true;
- CAM_DBG(CAM_ISP, "apply_bw_update=%d", apply_bw_update);
+ CAM_DBG(CAM_ISP, "apply_bw_update=%d", apply_bw_update);
- if (apply_bw_update == true) {
- rc = cam_cpas_update_axi_vote(
- soc_private->cpas_handle,
- &to_be_applied_axi_vote);
- if (!rc) {
- top_priv->applied_axi_vote.uncompressed_bw =
+ if (apply_bw_update == true) {
+ rc = cam_cpas_update_axi_vote(
+ soc_private->cpas_handle[cpashdl_type],
+ &to_be_applied_axi_vote);
+ if (!rc) {
+ top_priv->applied_axi_vote.uncompressed_bw =
to_be_applied_axi_vote.uncompressed_bw;
- top_priv->applied_axi_vote.compressed_bw =
- to_be_applied_axi_vote.compressed_bw;
- } else {
- CAM_ERR(CAM_ISP, "BW request failed, rc=%d", rc);
+ top_priv->applied_axi_vote.compressed_bw =
+ to_be_applied_axi_vote.compressed_bw;
+ } else {
+ CAM_ERR(CAM_ISP, "BW request failed, rc=%d",
+ rc);
+ }
}
}
-
return rc;
}
+static int cam_vfe_top_fs_update(
+ struct cam_vfe_top_ver2_priv *top_priv,
+ void *cmd_args, uint32_t arg_size)
+{
+ struct cam_vfe_fe_update_args *cmd_update = cmd_args;
+
+ if (cmd_update->node_res->process_cmd)
+ return cmd_update->node_res->process_cmd(cmd_update->node_res,
+ CAM_ISP_HW_CMD_FE_UPDATE_IN_RD, cmd_args, arg_size);
+
+ return 0;
+}
+
static int cam_vfe_top_clock_update(
struct cam_vfe_top_ver2_priv *top_priv,
void *cmd_args, uint32_t arg_size)
@@ -476,6 +510,14 @@ int cam_vfe_top_reserve(void *device_priv,
break;
}
+ if (acquire_args->res_id == CAM_ISP_HW_VFE_IN_RD) {
+ rc = cam_vfe_fe_ver1_acquire_resource(
+ &top_priv->mux_rsrc[i],
+ args);
+ if (rc)
+ break;
+ }
+
top_priv->mux_rsrc[i].cdm_ops = acquire_args->cdm_ops;
top_priv->mux_rsrc[i].tasklet_info = args->tasklet;
top_priv->mux_rsrc[i].res_state =
@@ -583,6 +625,7 @@ int cam_vfe_top_stop(void *device_priv,
if ((mux_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF) ||
(mux_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF_LITE) ||
+ (mux_res->res_id == CAM_ISP_HW_VFE_IN_RD) ||
((mux_res->res_id >= CAM_ISP_HW_VFE_IN_RDI0) &&
(mux_res->res_id <= CAM_ISP_HW_VFE_IN_RDI3))) {
rc = mux_res->stop(mux_res);
@@ -643,6 +686,10 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type,
rc = cam_vfe_top_clock_update(top_priv, cmd_args,
arg_size);
break;
+ case CAM_ISP_HW_CMD_FE_UPDATE_IN_RD:
+ rc = cam_vfe_top_fs_update(top_priv, cmd_args,
+ arg_size);
+ break;
case CAM_ISP_HW_CMD_BW_UPDATE:
rc = cam_vfe_top_bw_update(top_priv, cmd_args,
arg_size);
@@ -669,6 +716,7 @@ int cam_vfe_top_ver2_init(
struct cam_vfe_top_ver2_priv *top_priv = NULL;
struct cam_vfe_top_ver2_hw_info *ver2_hw_info = top_hw_info;
struct cam_vfe_top *vfe_top;
+ struct cam_vfe_soc_private *soc_private = NULL;
vfe_top = kzalloc(sizeof(struct cam_vfe_top), GFP_KERNEL);
if (!vfe_top) {
@@ -684,14 +732,22 @@ int cam_vfe_top_ver2_init(
rc = -ENOMEM;
goto free_vfe_top;
}
+
+ soc_private = soc_info->soc_private;
+ if (!soc_private) {
+ CAM_ERR(CAM_ISP, "Error! soc_private NULL");
+ rc = -ENODEV;
+ goto free_vfe_top_priv;
+ }
vfe_top->top_priv = top_priv;
top_priv->hw_clk_rate = 0;
top_priv->applied_axi_vote.compressed_bw = 0;
top_priv->applied_axi_vote.uncompressed_bw = 0;
memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) *
- (CAM_VFE_TOP_VER2_MUX_MAX *
+ (CAM_VFE_TOP_VER2_MUX_MAX * CAM_CPAS_HANDLE_MAX *
CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES));
- top_priv->last_counter = 0;
+ top_priv->last_counter[0] = 0;
+ top_priv->last_counter[1] = 0;
for (i = 0, j = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) {
top_priv->mux_rsrc[i].res_type = CAM_ISP_RESOURCE_VFE_IN;
@@ -707,6 +763,7 @@ int cam_vfe_top_ver2_init(
if (ver2_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_2_0) {
top_priv->mux_rsrc[i].res_id =
CAM_ISP_HW_VFE_IN_CAMIF;
+ top_priv->cpashdl_type[i] = CAM_CPAS_HANDLE_CAMIF;
rc = cam_vfe_camif_ver2_init(hw_intf, soc_info,
&ver2_hw_info->camif_hw_info,
@@ -717,6 +774,13 @@ int cam_vfe_top_ver2_init(
CAM_VFE_CAMIF_LITE_VER_2_0) {
top_priv->mux_rsrc[i].res_id =
CAM_ISP_HW_VFE_IN_CAMIF_LITE;
+ if (soc_private->cpas_version ==
+ CAM_CPAS_TITAN_175_V120)
+ top_priv->cpashdl_type[i] =
+ CAM_CPAS_HANDLE_RAW;
+ else
+ top_priv->cpashdl_type[i] =
+ CAM_CPAS_HANDLE_CAMIF;
rc = cam_vfe_camif_lite_ver2_init(hw_intf, soc_info,
&ver2_hw_info->camif_lite_hw_info,
@@ -729,12 +793,30 @@ int cam_vfe_top_ver2_init(
/* set the RDI resource id */
top_priv->mux_rsrc[i].res_id =
CAM_ISP_HW_VFE_IN_RDI0 + j++;
+ if (soc_private->cpas_version ==
+ CAM_CPAS_TITAN_175_V120)
+ top_priv->cpashdl_type[i] =
+ CAM_CPAS_HANDLE_RAW;
+ else
+ top_priv->cpashdl_type[i] =
+ CAM_CPAS_HANDLE_CAMIF;
rc = cam_vfe_rdi_ver2_init(hw_intf, soc_info,
&ver2_hw_info->rdi_hw_info,
&top_priv->mux_rsrc[i]);
if (rc)
goto deinit_resources;
+ } else if (ver2_hw_info->mux_type[i] ==
+ CAM_VFE_IN_RD_VER_1_0) {
+ /* set the RD resource id */
+ top_priv->mux_rsrc[i].res_id =
+ CAM_ISP_HW_VFE_IN_RD;
+
+ rc = cam_vfe_fe_ver1_init(hw_intf, soc_info,
+ &ver2_hw_info->fe_hw_info,
+ &top_priv->mux_rsrc[i]);
+ if (rc)
+ goto deinit_resources;
} else {
CAM_WARN(CAM_ISP, "Invalid mux type: %u",
ver2_hw_info->mux_type[i]);
@@ -769,6 +851,12 @@ deinit_resources:
if (cam_vfe_camif_lite_ver2_deinit(
&top_priv->mux_rsrc[i]))
CAM_ERR(CAM_ISP, "Camif lite deinit failed");
+ } else if (ver2_hw_info->mux_type[i] ==
+ CAM_ISP_HW_VFE_IN_RDI0) {
+ if (cam_vfe_rdi_ver2_init(hw_intf, soc_info,
+ &ver2_hw_info->rdi_hw_info,
+ &top_priv->mux_rsrc[i]))
+ CAM_ERR(CAM_ISP, "RDI deinit failed");
} else {
if (cam_vfe_rdi_ver2_deinit(&top_priv->mux_rsrc[i]))
CAM_ERR(CAM_ISP, "RDI Deinit failed");
@@ -776,7 +864,7 @@ deinit_resources:
top_priv->mux_rsrc[i].res_state =
CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
}
-
+free_vfe_top_priv:
kfree(vfe_top->top_priv);
free_vfe_top:
kfree(vfe_top);
@@ -829,6 +917,12 @@ int cam_vfe_top_ver2_deinit(struct cam_vfe_top **vfe_top_ptr)
rc = cam_vfe_rdi_ver2_deinit(&top_priv->mux_rsrc[i]);
if (rc)
CAM_ERR(CAM_ISP, "RDI deinit failed rc=%d", rc);
+ } else if (top_priv->mux_rsrc[i].res_type ==
+ CAM_VFE_IN_RD_VER_1_0) {
+ rc = cam_vfe_fe_ver1_deinit(&top_priv->mux_rsrc[i]);
+ if (rc)
+ CAM_ERR(CAM_ISP, "Camif deinit failed rc=%d",
+ rc);
}
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h
index 11ca78cd8a2e..33435df476d1 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -16,8 +16,9 @@
#include "cam_vfe_camif_ver2.h"
#include "cam_vfe_camif_lite_ver2.h"
#include "cam_vfe_rdi.h"
+#include "cam_vfe_fe_ver1.h"
-#define CAM_VFE_TOP_VER2_MUX_MAX 5
+#define CAM_VFE_TOP_VER2_MUX_MAX 6
enum cam_vfe_top_ver2_module_type {
CAM_VFE_TOP_VER2_MODULE_LENS,
@@ -55,6 +56,7 @@ struct cam_vfe_top_ver2_hw_info {
struct cam_vfe_camif_ver2_hw_info camif_hw_info;
struct cam_vfe_camif_lite_ver2_hw_info camif_lite_hw_info;
struct cam_vfe_rdi_ver2_hw_info rdi_hw_info;
+ struct cam_vfe_fe_ver1_hw_info fe_hw_info;
uint32_t mux_type[CAM_VFE_TOP_VER2_MUX_MAX];
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h
index 90c75291bd73..cee2b4a96cb4 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -24,7 +24,8 @@
#define CAM_VFE_CAMIF_LITE_VER_2_0 0x02
-#define CAM_VFE_RDI_VER_1_0 0x1000
+#define CAM_VFE_RDI_VER_1_0 0x1000
+#define CAM_VFE_IN_RD_VER_1_0 0x2000
struct cam_vfe_top {
void *top_priv;
diff --git a/drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
index 24bb154f922c..f27b54a81e4a 100644
--- a/drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -258,7 +258,7 @@ static int cam_jpeg_insert_cdm_change_base(
struct cam_jpeg_hw_ctx_data *ctx_data,
struct cam_jpeg_hw_mgr *hw_mgr)
{
- int rc;
+ int rc = 0;
uint32_t dev_type;
struct cam_cdm_bl_request *cdm_cmd;
uint32_t size;
@@ -275,6 +275,12 @@ static int cam_jpeg_insert_cdm_change_base(
"unable to get src buf info for cmd buf: %d", rc);
return rc;
}
+
+ if (config_args->hw_update_entries[CAM_JPEG_CHBASE].offset >=
+ ch_base_len) {
+ CAM_ERR(CAM_JPEG, "Not enough buf");
+ return -EINVAL;
+ }
CAM_DBG(CAM_JPEG, "iova %pK len %zu offset %d",
(void *)iova_addr, ch_base_len,
config_args->hw_update_entries[CAM_JPEG_CHBASE].offset);
@@ -713,7 +719,7 @@ static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv,
return -EINVAL;
}
- rc = cam_packet_util_validate_packet(packet);
+ rc = cam_packet_util_validate_packet(packet, prepare_args->remain_len);
if (rc) {
CAM_ERR(CAM_JPEG, "invalid packet %d", rc);
return rc;
diff --git a/drivers/media/platform/msm/camera_v3/cam_lrme/Makefile b/drivers/media/platform/msm/camera_v3/cam_lrme/Makefile
index 5e46bf2531f8..83a580c23bc2 100644
--- a/drivers/media/platform/msm/camera_v3/cam_lrme/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_lrme/Makefile
@@ -7,7 +7,7 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cdm
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_lrme
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/lrme_hw
-ccflags-y += -Idrivers/media/platform/msm/camera
+ccflags-y += -Idrivers/media/platform/msm/camera_v3
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cpas/include/
obj-$(CONFIG_SPECTRA_CAMERA) += lrme_hw_mgr/
diff --git a/drivers/media/platform/msm/camera_v3/cam_lrme/cam_lrme_context.h b/drivers/media/platform/msm/camera_v3/cam_lrme/cam_lrme_context.h
index dc1c8f4c10aa..b8d0357f6f3d 100644
--- a/drivers/media/platform/msm/camera_v3/cam_lrme/cam_lrme_context.h
+++ b/drivers/media/platform/msm/camera_v3/cam_lrme/cam_lrme_context.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -19,7 +19,7 @@
#include "cam_req_mgr_interface.h"
#include "cam_sync_api.h"
-#define CAM_LRME_CTX_INDEX_SHIFT 16
+#define CAM_LRME_CTX_INDEX_SHIFT 32
/**
* struct cam_lrme_context
diff --git a/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/Makefile b/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/Makefile
index a048afece9db..2a4fba727773 100644
--- a/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/Makefile
@@ -7,7 +7,7 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cdm
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_lrme
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/lrme_hw
-ccflags-y += -Idrivers/media/platform/msm/camera
+ccflags-y += -Idrivers/media/platform/msm/camera_v3
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cpas/include
obj-$(CONFIG_SPECTRA_CAMERA) += lrme_hw/
diff --git a/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
index 0c236462b7f5..47bf68c16c03 100644
--- a/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -83,7 +83,8 @@ static int cam_lrme_mgr_util_get_device(struct cam_lrme_hw_mgr *hw_mgr,
return 0;
}
-static int cam_lrme_mgr_util_packet_validate(struct cam_packet *packet)
+static int cam_lrme_mgr_util_packet_validate(struct cam_packet *packet,
+ size_t remain_len)
{
struct cam_cmd_buf_desc *cmd_desc = NULL;
int i, rc;
@@ -105,7 +106,7 @@ static int cam_lrme_mgr_util_packet_validate(struct cam_packet *packet)
packet->patch_offset, packet->num_patches,
packet->kmd_cmd_buf_offset, packet->kmd_cmd_buf_index);
- if (cam_packet_util_validate_packet(packet)) {
+ if (cam_packet_util_validate_packet(packet, remain_len)) {
CAM_ERR(CAM_LRME, "invalid packet:%d %d %d %d %d",
packet->kmd_cmd_buf_index,
packet->num_cmd_buf, packet->cmd_buf_offset,
@@ -186,6 +187,12 @@ static int cam_lrme_mgr_util_prepare_io_buffer(int32_t iommu_hdl,
return -ENOMEM;
}
+ if ((size_t)io_cfg[i].offsets[plane] >= size) {
+ CAM_ERR(CAM_LRME, "Invalid plane offset: %zu",
+ (size_t)io_cfg[i].offsets[plane]);
+ return -EINVAL;
+ }
+
io_addr[plane] += io_cfg[i].offsets[plane];
CAM_DBG(CAM_LRME, "IO Address[%d][%d] : %llu",
@@ -841,7 +848,7 @@ static int cam_lrme_mgr_hw_prepare_update(void *hw_mgr_priv,
goto error;
}
- rc = cam_lrme_mgr_util_packet_validate(args->packet);
+ rc = cam_lrme_mgr_util_packet_validate(args->packet, args->remain_len);
if (rc) {
CAM_ERR(CAM_LRME, "Error in packet validation %d", rc);
goto error;
diff --git a/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c b/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
index 8cb1c9c28e7a..4220e5993dd5 100644
--- a/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -42,7 +42,10 @@ static void cam_lrme_hw_util_fill_fe_reg(struct cam_lrme_hw_io_buffer *io_buf,
uint32_t reg_val;
/* 1. config buffer size */
- reg_val = io_buf->io_cfg->planes[0].width;
+ if (io_buf->io_cfg->format == CAM_FORMAT_PLAIN16_10)
+ reg_val = io_buf->io_cfg->planes[0].width * 2;
+ else
+ reg_val = io_buf->io_cfg->planes[0].width;
reg_val |= (io_buf->io_cfg->planes[0].height << 16);
cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd,
hw_info->bus_rd_reg.bus_client_reg[index].rd_buffer_size,
@@ -736,6 +739,11 @@ int cam_lrme_hw_process_irq(void *priv, void *data)
mutex_lock(&lrme_hw->hw_mutex);
+ if (lrme_hw->hw_state == CAM_HW_STATE_POWER_DOWN) {
+ CAM_DBG(CAM_LRME, "LRME HW is in off state");
+ goto end;
+ }
+
if (top_irq_status & (1 << 3)) {
CAM_DBG(CAM_LRME, "Error");
rc = cam_lrme_hw_util_process_err(lrme_hw);
@@ -895,7 +903,7 @@ int cam_lrme_hw_stop(void *hw_priv, void *hw_stop_args, uint32_t arg_size)
lrme_core->state = CAM_LRME_CORE_STATE_INIT;
} else {
CAM_ERR(CAM_LRME, "HW in wrong state %d", lrme_core->state);
- return -EINVAL;
+ rc = -EINVAL;
}
unlock:
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr.c b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr.c
index 2d17f7b51cd7..cff48e599f04 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, 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
@@ -241,6 +241,13 @@ exit_func:
}
EXPORT_SYMBOL(cam_mem_get_cpu_buf);
+int cam_mem_put_cpu_buf(int32_t buf_handle)
+{
+ int rc = 0;
+ return rc;
+}
+EXPORT_SYMBOL(cam_mem_put_cpu_buf);
+
int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd)
{
int rc = 0, idx;
@@ -409,11 +416,6 @@ static int cam_mem_util_ion_alloc(struct cam_mem_mgr_alloc_cmd *cmd,
static int cam_mem_util_check_flags(struct cam_mem_mgr_alloc_cmd *cmd)
{
- if (!cmd->flags) {
- CAM_ERR(CAM_MEM, "Invalid flags");
- return -EINVAL;
- }
-
if (cmd->num_hdl > CAM_MEM_MMU_MAX_HANDLE) {
CAM_ERR(CAM_MEM, "Num of mmu hdl exceeded maximum(%d)",
CAM_MEM_MMU_MAX_HANDLE);
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr_api.h b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr_api.h
index 64258e8fb5ee..79945cff1dd2 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr_api.h
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -95,6 +95,15 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle,
int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr,
size_t *len);
+/**
+ * @brief: This indicates end of CPU access
+ *
+ * @buf_handle: Handle for the buffer
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int cam_mem_put_cpu_buf(int32_t buf_handle);
+
static inline bool cam_mem_is_secure_buf(int32_t buf_handle)
{
return CAM_MEM_MGR_IS_SECURE_HDL(buf_handle);
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c
index 275940f839e3..3e3be4f6281e 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, 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
@@ -24,6 +24,31 @@
#include "cam_req_mgr_dev.h"
static struct cam_req_mgr_core_device *g_crm_core_dev;
+static struct cam_req_mgr_core_link g_links[MAXIMUM_LINKS_PER_SESSION];
+
+void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
+{
+ link->link_hdl = 0;
+ link->num_devs = 0;
+ link->max_delay = CAM_PIPELINE_DELAY_0;
+ link->workq = NULL;
+ link->pd_mask = 0;
+ link->l_dev = NULL;
+ link->req.in_q = NULL;
+ link->req.l_tbl = NULL;
+ link->req.num_tbl = 0;
+ link->watchdog = NULL;
+ link->state = CAM_CRM_LINK_STATE_AVAILABLE;
+ link->parent = NULL;
+ link->subscribe_event = 0;
+ link->trigger_mask = 0;
+ link->sync_link = 0;
+ link->sync_link_sof_skip = false;
+ link->open_req_cnt = 0;
+ link->last_flush_id = 0;
+ link->initial_sync_req = -1;
+ link->in_msync_mode = false;
+}
void cam_req_mgr_handle_core_shutdown(void)
{
@@ -117,31 +142,35 @@ static void __cam_req_mgr_dec_idx(int32_t *val, int32_t step, int32_t max_val)
}
/**
- * __cam_req_mgr_validate_inject_delay()
+ * __cam_req_mgr_inject_delay()
*
- * @brief : Check if any pd device is introducing inject delay
+ * @brief : Check if any pd device is injecting delay
* @tbl : cam_req_mgr_req_tbl
* @curr_idx : slot idx
*
* @return : 0 for success, negative for failure
*/
-static int __cam_req_mgr_validate_inject_delay(
+static int __cam_req_mgr_inject_delay(
struct cam_req_mgr_req_tbl *tbl,
int32_t curr_idx)
{
struct cam_req_mgr_tbl_slot *slot = NULL;
+ int rc = 0;
while (tbl) {
slot = &tbl->slot[curr_idx];
if (slot->inject_delay > 0) {
slot->inject_delay--;
- return -EAGAIN;
+ CAM_DBG(CAM_CRM,
+ "Delay injected by pd %d device",
+ tbl->pd);
+ rc = -EAGAIN;
}
__cam_req_mgr_dec_idx(&curr_idx, tbl->pd_delta,
tbl->num_slots);
tbl = tbl->next;
}
- return 0;
+ return rc;
}
/**
@@ -183,19 +212,6 @@ static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data)
tbl->skip_traverse, traverse_data->in_q->slot[curr_idx].status,
traverse_data->in_q->slot[curr_idx].skip_idx);
- if ((traverse_data->self_link == true) &&
- (!traverse_data->inject_delay_chk)) {
- rc = __cam_req_mgr_validate_inject_delay(tbl, curr_idx);
- if (rc) {
- CAM_DBG(CAM_CRM, "Injecting Delay of one frame");
- apply_data[tbl->pd].req_id = -1;
- /* This pd tbl not ready to proceed with asked idx */
- SET_FAILURE_BIT(traverse_data->result, tbl->pd);
- return -EAGAIN;
- }
- traverse_data->inject_delay_chk = true;
- }
-
/* Check if req is ready or in skip mode or pd tbl is in skip mode */
if (tbl->slot[curr_idx].state == CRM_REQ_STATE_READY ||
traverse_data->in_q->slot[curr_idx].skip_idx == 1 ||
@@ -356,6 +372,30 @@ static void __cam_req_mgr_reset_req_slot(struct cam_req_mgr_core_link *link,
}
/**
+ * __cam_req_mgr_check_for_lower_pd_devices()
+ *
+ * @brief : Checks if there are any devices on the link having a lesser
+ * pd than the max pd of the link
+ * @link : Pointer to link which needs to be checked
+ *
+ * @return : 0 if a lower pd device is found negative otherwise
+ */
+static int __cam_req_mgr_check_for_lower_pd_devices(
+ struct cam_req_mgr_core_link *link)
+{
+ int i = 0;
+ struct cam_req_mgr_connected_device *dev = NULL;
+
+ for (i = 0; i < link->num_devs; i++) {
+ dev = &link->l_dev[i];
+ if (dev->dev_info.p_delay < link->max_delay)
+ return 0;
+ }
+
+ return -EAGAIN;
+}
+
+/**
* __cam_req_mgr_check_next_req_slot()
*
* @brief : While streaming if input queue does not contain any pending
@@ -363,11 +403,14 @@ static void __cam_req_mgr_reset_req_slot(struct cam_req_mgr_core_link *link,
* devices with lower pipeline delay value.
* @in_q : Pointer to input queue where req mgr wil peep into
*
+ * @return : 0 for success, negative for failure
*/
-static void __cam_req_mgr_check_next_req_slot(
- struct cam_req_mgr_req_queue *in_q)
+static int __cam_req_mgr_check_next_req_slot(
+ struct cam_req_mgr_core_link *link)
{
- int32_t idx = in_q->rd_idx;
+ int rc = 0;
+ struct cam_req_mgr_req_queue *in_q = link->req.in_q;
+ int32_t idx = in_q->rd_idx;
struct cam_req_mgr_slot *slot;
__cam_req_mgr_inc_idx(&idx, 1, in_q->num_slots);
@@ -377,12 +420,20 @@ static void __cam_req_mgr_check_next_req_slot(
/* Check if there is new req from CSL, if not complete req */
if (slot->status == CRM_SLOT_STATUS_NO_REQ) {
+ rc = __cam_req_mgr_check_for_lower_pd_devices(link);
+ if (rc) {
+ CAM_DBG(CAM_CRM, "No lower pd devices on link 0x%x",
+ link->link_hdl);
+ return rc;
+ }
__cam_req_mgr_in_q_skip_idx(in_q, idx);
if (in_q->wr_idx != idx)
CAM_WARN(CAM_CRM,
"CHECK here wr %d, rd %d", in_q->wr_idx, idx);
__cam_req_mgr_inc_idx(&in_q->wr_idx, 1, in_q->num_slots);
}
+
+ return rc;
}
/**
@@ -483,8 +534,6 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
continue;
}
- trace_cam_req_mgr_apply_request(link, &apply_req, dev);
-
apply_req.trigger_point = trigger;
CAM_DBG(CAM_REQ,
"SEND: link_hdl: %x pd %d req_id %lld",
@@ -497,6 +546,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
if (pd == link->max_delay)
link->open_req_cnt--;
}
+ trace_cam_req_mgr_apply_request(link, &apply_req, dev);
}
}
if (rc < 0) {
@@ -526,14 +576,12 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
* traversed through
* @idx : index within input request queue
* @validate_only : Whether to validate only and/or update settings
- * @self_link : To indicate whether the validation is for the given link or
- * other sync link
*
* @return : 0 for success, negative for failure
*
*/
static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link,
- int32_t idx, bool validate_only, bool self_link)
+ int32_t idx, bool validate_only)
{
int rc;
struct cam_req_mgr_traverse traverse_data;
@@ -555,19 +603,16 @@ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link,
traverse_data.in_q = in_q;
traverse_data.result = 0;
traverse_data.validate_only = validate_only;
- traverse_data.self_link = self_link;
- traverse_data.inject_delay_chk = false;
traverse_data.open_req_cnt = link->open_req_cnt;
+
/*
* Traverse through all pd tables, if result is success,
* apply the settings
*/
-
rc = __cam_req_mgr_traverse(&traverse_data);
CAM_DBG(CAM_CRM,
- "SOF: idx %d self_link %d validate %d result %x pd_mask %x rc %d",
- idx, traverse_data.self_link, traverse_data.validate_only,
- traverse_data.result, link->pd_mask, rc);
+ "SOF: idx %d result %x pd_mask %x rc %d",
+ idx, traverse_data.result, link->pd_mask, rc);
if (!rc && traverse_data.result == link->pd_mask) {
CAM_DBG(CAM_CRM,
@@ -616,113 +661,218 @@ static int32_t __cam_req_mgr_find_slot_for_req(
}
/**
- * __cam_req_mgr_reset_sof_cnt()
+ * __cam_req_mgr_check_sync_for_mslave()
*
- * @brief : the sof_count for both the links are reset
- * @link : pointer to link whose input queue and req tbl are
+ * @brief : Processes requests during sync mode [master-slave]
+ * Here master corresponds to the link having a higher
+ * max_delay (pd) compared to the slave link.
+ * @link : Pointer to link whose input queue and req tbl are
* traversed through
+ * @slot : Pointer to the current slot being processed
+ * @return : 0 for success, negative for failure
*
*/
-static void __cam_req_mgr_reset_sof_cnt(
- struct cam_req_mgr_core_link *link)
+static int __cam_req_mgr_check_sync_for_mslave(
+ struct cam_req_mgr_core_link *link,
+ struct cam_req_mgr_slot *slot)
{
- link->sof_counter = -1;
- link->sync_link->sof_counter = -1;
- link->frame_skip_flag = false;
+ struct cam_req_mgr_core_link *sync_link = NULL;
+ struct cam_req_mgr_slot *sync_slot = NULL;
+ int sync_slot_idx = 0, prev_idx, next_idx, rd_idx, sync_rd_idx, rc = 0;
+ int64_t req_id = 0, sync_req_id = 0;
- CAM_DBG(CAM_CRM,
- "link_hdl %x self_counter %lld other_counter %lld frame_skip_lag %d",
- link->link_hdl, link->sof_counter,
- link->sync_link->sof_counter, link->frame_skip_flag);
-}
+ if (!link->sync_link) {
+ CAM_ERR(CAM_CRM, "Sync link null");
+ return -EINVAL;
+ }
-/**
- * __cam_req_mgr_sof_cnt_initialize()
- *
- * @brief : when the sof count is intially -1 it increments count
- * and computes the sync_self_ref for this link
- * the count needs to be wrapped back starting from 0
- * @link : pointer to link whose input queue and req tbl are
- * traversed through
- *
- */
-static void __cam_req_mgr_sof_cnt_initialize(
- struct cam_req_mgr_core_link *link)
-{
- link->sof_counter++;
- link->sync_self_ref = link->sof_counter -
- link->sync_link->sof_counter;
+ sync_link = link->sync_link;
+ req_id = slot->req_id;
+ sync_rd_idx = sync_link->req.in_q->rd_idx;
CAM_DBG(CAM_CRM,
- "link_hdl %x self_counter %lld other_counter %lld",
- link->link_hdl, link->sof_counter,
- link->sync_link->sof_counter);
-}
+ "link_hdl %x req %lld frame_skip_flag %d open_req_cnt:%d initial_sync_req [%lld,%lld] is_master:%d",
+ link->link_hdl, req_id, link->sync_link_sof_skip,
+ link->open_req_cnt, link->initial_sync_req,
+ sync_link->initial_sync_req, link->is_master);
-/**
- * __cam_req_mgr_wrap_sof_cnt()
- *
- * @brief : once the sof count reaches a predefined maximum
- * the count needs to be wrapped back starting from 0
- * @link : pointer to link whose input queue and req tbl are
- * traversed through
- *
- */
-static void __cam_req_mgr_wrap_sof_cnt(
- struct cam_req_mgr_core_link *link)
-{
- link->sof_counter = (MAX_SYNC_COUNT -
- (link->sync_link->sof_counter));
- link->sync_link->sof_counter = 0;
+ if (sync_link->sync_link_sof_skip) {
+ CAM_DBG(CAM_CRM,
+ "No req applied on corresponding SOF on sync link: %x",
+ sync_link->link_hdl);
+ sync_link->sync_link_sof_skip = false;
+ __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
+ return -EAGAIN;
+ }
- CAM_DBG(CAM_CRM,
- "link_hdl %x self_counter %lld sync_link_hdl %x other_counter %lld",
- link->link_hdl, link->sof_counter,
- link->sync_link->link_hdl, link->sync_link->sof_counter);
-}
+ if (link->in_msync_mode &&
+ sync_link->in_msync_mode &&
+ (req_id - sync_link->req.in_q->slot[sync_rd_idx].req_id >
+ link->max_delay - sync_link->max_delay)) {
+ CAM_DBG(CAM_CRM,
+ "Req: %lld on link:%x need to hold for link: %x req:%d",
+ req_id,
+ link->link_hdl,
+ sync_link->link_hdl,
+ sync_link->req.in_q->slot[sync_rd_idx].req_id);
+ return -EINVAL;
+ }
-/**
- * __cam_req_mgr_validate_sof_cnt()
- *
- * @brief : validates sof count difference for a given link
- * @link : pointer to link whose input queue and req tbl are
- * traversed through
- * @sync_link : pointer to the sync link
- * @return : 0 for success, negative for failure
- *
- */
-static int __cam_req_mgr_validate_sof_cnt(
- struct cam_req_mgr_core_link *link,
- struct cam_req_mgr_core_link *sync_link)
-{
- int64_t sync_diff = 0;
- int rc = 0;
+ if (link->is_master) {
+ rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
+ if (rc) {
+ CAM_DBG(CAM_CRM,
+ "Skip Process Req: %lld on link: %x",
+ req_id, link->link_hdl);
+ link->sync_link_sof_skip = true;
+ return rc;
+ }
- if (link->sof_counter == MAX_SYNC_COUNT)
- __cam_req_mgr_wrap_sof_cnt(link);
+ if (sync_link->initial_skip) {
+ CAM_DBG(CAM_CRM, "Link 0x%x [slave] not streamed on",
+ sync_link->link_hdl);
+ return -EAGAIN;
+ }
- sync_diff = link->sof_counter - sync_link->sof_counter;
+ rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true);
+ if (rc) {
+ CAM_DBG(CAM_CRM,
+ "Req: %lld [master] not ready on link: %x, rc=%d",
+ req_id, link->link_hdl, rc);
+ link->sync_link_sof_skip = true;
+ return rc;
+ }
- CAM_DBG(CAM_CRM,
- "link[%x] self_counter=%lld other_counter=%lld diff=%lld sync_self_ref=%lld",
- link->link_hdl, link->sof_counter,
- sync_link->sof_counter, sync_diff, link->sync_self_ref);
-
- if (sync_diff > SYNC_LINK_SOF_CNT_MAX_LMT) {
- link->sync_link->frame_skip_flag = true;
- CAM_WARN(CAM_CRM,
- "Detected anomaly, skip link_hdl %x self_counter=%lld other_counter=%lld sync_self_ref=%lld",
- link->link_hdl, link->sof_counter,
- sync_link->sof_counter, link->sync_self_ref);
- rc = -EPERM;
+ prev_idx = slot->idx;
+ __cam_req_mgr_dec_idx(&prev_idx,
+ (link->max_delay - sync_link->max_delay),
+ link->req.in_q->num_slots);
+
+ rd_idx = sync_link->req.in_q->rd_idx;
+ sync_req_id = link->req.in_q->slot[prev_idx].req_id;
+ if ((sync_link->initial_sync_req != -1) &&
+ (sync_link->initial_sync_req <= sync_req_id)) {
+ sync_slot_idx = __cam_req_mgr_find_slot_for_req(
+ sync_link->req.in_q, sync_req_id);
+
+ if (sync_slot_idx == -1) {
+ CAM_DBG(CAM_CRM,
+ "Prev Req: %lld [master] not found on link: %x [slave]",
+ sync_req_id, sync_link->link_hdl);
+ link->sync_link_sof_skip = true;
+ return -EINVAL;
+ }
+
+ if ((sync_link->req.in_q->slot[sync_slot_idx].status !=
+ CRM_SLOT_STATUS_REQ_APPLIED) &&
+ ((sync_slot_idx - rd_idx) >= 1) &&
+ (sync_link->req.in_q->slot[rd_idx].status !=
+ CRM_SLOT_STATUS_REQ_APPLIED)) {
+ CAM_DBG(CAM_CRM,
+ "Prev Req: %lld [master] not next on link: %x [slave]",
+ sync_req_id,
+ sync_link->link_hdl);
+ return -EINVAL;
+ }
+
+ rc = __cam_req_mgr_check_link_is_ready(sync_link,
+ sync_slot_idx, true);
+ if (rc &&
+ (sync_link->req.in_q->slot[sync_slot_idx].status
+ != CRM_SLOT_STATUS_REQ_APPLIED)) {
+ CAM_DBG(CAM_CRM,
+ "Req: %lld not ready on [slave] link: %x, rc=%d",
+ sync_req_id, sync_link->link_hdl, rc);
+ link->sync_link_sof_skip = true;
+ return rc;
+ }
+ }
+ } else {
+ if (link->initial_skip)
+ link->initial_skip = false;
+
+ rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
+ if (rc) {
+ CAM_DBG(CAM_CRM,
+ "Skip Process Req: %lld on link: %x",
+ req_id, link->link_hdl);
+ link->sync_link_sof_skip = true;
+ return rc;
+ }
+
+ rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true);
+ if (rc) {
+ CAM_DBG(CAM_CRM,
+ "Req: %lld [slave] not ready on link: %x, rc=%d",
+ req_id, link->link_hdl, rc);
+ link->sync_link_sof_skip = true;
+ return rc;
+ }
+
+ next_idx = link->req.in_q->rd_idx;
+ rd_idx = sync_link->req.in_q->rd_idx;
+ __cam_req_mgr_inc_idx(&next_idx,
+ (sync_link->max_delay - link->max_delay),
+ link->req.in_q->num_slots);
+
+ sync_req_id = link->req.in_q->slot[next_idx].req_id;
+
+ if ((sync_link->initial_sync_req != -1) &&
+ (sync_link->initial_sync_req <= sync_req_id)) {
+ sync_slot_idx = __cam_req_mgr_find_slot_for_req(
+ sync_link->req.in_q, sync_req_id);
+ if (sync_slot_idx == -1) {
+ CAM_DBG(CAM_CRM,
+ "Next Req: %lld [slave] not found on link: %x [master]",
+ sync_req_id, sync_link->link_hdl);
+ link->sync_link_sof_skip = true;
+ return -EINVAL;
+ }
+
+ if ((sync_link->req.in_q->slot[sync_slot_idx].status !=
+ CRM_SLOT_STATUS_REQ_APPLIED) &&
+ ((sync_slot_idx - rd_idx) >= 1) &&
+ (sync_link->req.in_q->slot[rd_idx].status !=
+ CRM_SLOT_STATUS_REQ_APPLIED)) {
+ CAM_DBG(CAM_CRM,
+ "Next Req: %lld [slave] not next on link: %x [master]",
+ sync_req_id, sync_link->link_hdl);
+ return -EINVAL;
+ }
+
+ sync_slot = &sync_link->req.in_q->slot[sync_slot_idx];
+ rc = __cam_req_mgr_check_link_is_ready(sync_link,
+ sync_slot_idx, true);
+ if (rc && (sync_slot->status !=
+ CRM_SLOT_STATUS_REQ_APPLIED)) {
+ CAM_DBG(CAM_CRM,
+ "Next Req: %lld [slave] not ready on [master] link: %x, rc=%d",
+ sync_req_id, sync_link->link_hdl, rc);
+ link->sync_link_sof_skip = true;
+ return rc;
+ }
+ }
}
- return rc;
+ CAM_DBG(CAM_REQ,
+ "Req: %lld ready to apply on link: %x [validation successful]",
+ req_id, link->link_hdl);
+
+ /*
+ * At this point all validation is successfully done
+ * and we can proceed to apply the given request.
+ * Ideally the next call should return success.
+ */
+ rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, false);
+ if (rc)
+ CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc);
+
+ return 0;
}
/**
- * __cam_req_mgr_process_sync_req()
+ * __cam_req_mgr_check_sync_request_is_ready()
*
* @brief : processes requests during sync mode
* @link : pointer to link whose input queue and req tbl are
@@ -731,13 +881,13 @@ static int __cam_req_mgr_validate_sof_cnt(
* @return : 0 for success, negative for failure
*
*/
-static int __cam_req_mgr_process_sync_req(
+static int __cam_req_mgr_check_sync_req_is_ready(
struct cam_req_mgr_core_link *link,
struct cam_req_mgr_slot *slot)
{
struct cam_req_mgr_core_link *sync_link = NULL;
int64_t req_id = 0;
- int sync_slot_idx = 0, rc = 0;
+ int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0;
if (!link->sync_link) {
CAM_ERR(CAM_CRM, "Sync link null");
@@ -748,94 +898,81 @@ static int __cam_req_mgr_process_sync_req(
req_id = slot->req_id;
CAM_DBG(CAM_REQ,
- "link_hdl %x req %lld sync_self_ref %lld sof_counter %lld frame_skip_flag %d sync_link_self_ref %lld",
- link->link_hdl, req_id, link->sync_self_ref, link->sof_counter,
- link->frame_skip_flag, link->sync_link->sync_self_ref);
+ "link_hdl %x req %lld frame_skip_flag %d ",
+ link->link_hdl, req_id, link->sync_link_sof_skip);
if (sync_link->sync_link_sof_skip) {
CAM_DBG(CAM_REQ,
"No req applied on corresponding SOF on sync link: %x",
sync_link->link_hdl);
sync_link->sync_link_sof_skip = false;
- /*It is to manage compensate inject delay for each pd*/
- __cam_req_mgr_check_link_is_ready(link, slot->idx, true, true);
- return -EINVAL;
+ __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
+ return -EAGAIN;
}
- if (link->sof_counter == -1) {
- __cam_req_mgr_sof_cnt_initialize(link);
- } else if ((link->frame_skip_flag) &&
- (sync_link->sync_self_ref != -1)) {
- CAM_DBG(CAM_REQ, "Link[%x] Req[%lld] Resetting values ",
- link->link_hdl, req_id);
- __cam_req_mgr_reset_sof_cnt(link);
- __cam_req_mgr_sof_cnt_initialize(link);
- } else {
- link->sof_counter++;
+ rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
+ if (rc) {
+ CAM_DBG(CAM_CRM,
+ "Skip Process Req: %lld on link: %x",
+ req_id, link->link_hdl);
+ link->sync_link_sof_skip = true;
+ return rc;
}
- rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true, true);
+ rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true);
if (rc) {
- CAM_DBG(CAM_REQ,
+ CAM_DBG(CAM_CRM,
"Req: %lld [My link] not ready on link: %x, rc=%d",
req_id, link->link_hdl, rc);
link->sync_link_sof_skip = true;
- goto failure;
+ return rc;
}
sync_slot_idx = __cam_req_mgr_find_slot_for_req(
sync_link->req.in_q, req_id);
-
- if (sync_slot_idx != -1) {
- rc = __cam_req_mgr_check_link_is_ready(
- sync_link, sync_slot_idx, true, false);
- CAM_DBG(CAM_CRM, "sync_slot_idx=%d, status=%d, rc=%d",
- sync_slot_idx,
- sync_link->req.in_q->slot[sync_slot_idx].status,
- rc);
- } else {
- CAM_DBG(CAM_CRM, "sync_slot_idx=%d, rc=%d",
- sync_slot_idx, rc);
+ if (sync_slot_idx == -1) {
+ CAM_DBG(CAM_CRM, "Req: %lld not found on link: %x [other link]",
+ req_id, sync_link->link_hdl);
+ link->sync_link_sof_skip = true;
+ return -EINVAL;
}
- if ((sync_slot_idx != -1) &&
- ((sync_link->req.in_q->slot[sync_slot_idx].status ==
- CRM_SLOT_STATUS_REQ_APPLIED) || (rc == 0))) {
- rc = __cam_req_mgr_validate_sof_cnt(link, sync_link);
- if (rc) {
- CAM_DBG(CAM_CRM,
- "Req: %lld validate failed: %x",
- req_id, sync_link->link_hdl);
- goto failure;
- }
-
- CAM_DBG(CAM_REQ,
- "Req: %lld ready to apply on link: %x [validation successful]",
- req_id, link->link_hdl);
- /*
- * At this point all validation is successfully done
- * and we can proceed to apply the given request.
- * Ideally the next call should return success.
- */
- rc = __cam_req_mgr_check_link_is_ready(link,
- slot->idx, false, true);
-
- if (rc)
- CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc);
- } else {
- CAM_DBG(CAM_REQ,
- "Req: %lld [Other link] not ready to apply on link: %x",
+ sync_rd_idx = sync_link->req.in_q->rd_idx;
+ if ((sync_link->req.in_q->slot[sync_slot_idx].status !=
+ CRM_SLOT_STATUS_REQ_APPLIED) &&
+ ((sync_slot_idx - sync_rd_idx) >= 1) &&
+ (sync_link->req.in_q->slot[sync_rd_idx].status !=
+ CRM_SLOT_STATUS_REQ_APPLIED)) {
+ CAM_DBG(CAM_CRM,
+ "Req: %lld [other link] not next req to be applied on link: %x",
req_id, sync_link->link_hdl);
- rc = -EPERM;
+ return -EAGAIN;
+ }
+
+ rc = __cam_req_mgr_check_link_is_ready(sync_link, sync_slot_idx, true);
+ if (rc && (sync_link->req.in_q->slot[sync_slot_idx].status !=
+ CRM_SLOT_STATUS_REQ_APPLIED)) {
+ CAM_DBG(CAM_CRM,
+ "Req: %lld not ready on [other link] link: %x, rc=%d",
+ req_id, sync_link->link_hdl, rc);
link->sync_link_sof_skip = true;
- goto failure;
+ return rc;
}
- return rc;
+ CAM_DBG(CAM_REQ,
+ "Req: %lld ready to apply on link: %x [validation successful]",
+ req_id, link->link_hdl);
-failure:
- link->sof_counter--;
- return rc;
+ /*
+ * At this point all validation is successfully done
+ * and we can proceed to apply the given request.
+ * Ideally the next call should return success.
+ */
+ rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, false);
+ if (rc)
+ CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc);
+
+ return 0;
}
/**
@@ -896,11 +1033,41 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
goto error;
}
- if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC)
- rc = __cam_req_mgr_process_sync_req(link, slot);
- else
- rc = __cam_req_mgr_check_link_is_ready(link,
- slot->idx, false, true);
+ if ((slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) &&
+ (link->sync_link)) {
+ if (link->is_master || link->sync_link->is_master) {
+ if (!link->in_msync_mode) {
+ CAM_DBG(CAM_CRM,
+ "Settings master-slave sync mode for link 0x%x",
+ link->link_hdl);
+ link->in_msync_mode = true;
+ }
+
+ rc = __cam_req_mgr_check_sync_for_mslave(
+ link, slot);
+ } else {
+ rc = __cam_req_mgr_check_sync_req_is_ready(
+ link, slot);
+ }
+ } else {
+ if (link->in_msync_mode) {
+ CAM_DBG(CAM_CRM,
+ "Settings master-slave non sync mode for link 0x%x",
+ link->link_hdl);
+ link->in_msync_mode = false;
+ link->initial_sync_req = -1;
+ if (link->sync_link) {
+ link->sync_link->initial_sync_req = -1;
+ link->sync_link->in_msync_mode = false;
+ }
+ }
+
+ rc = __cam_req_mgr_inject_delay(link->req.l_tbl,
+ slot->idx);
+ if (!rc)
+ rc = __cam_req_mgr_check_link_is_ready(link,
+ slot->idx, false);
+ }
if (rc < 0) {
/*
@@ -1344,25 +1511,25 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link(
session->num_links, MAXIMUM_LINKS_PER_SESSION);
return NULL;
}
-
- link = (struct cam_req_mgr_core_link *)
- kzalloc(sizeof(struct cam_req_mgr_core_link), GFP_KERNEL);
- if (!link) {
- CAM_ERR(CAM_CRM, "failed to create link, no mem");
- return NULL;
+ for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
+ if (!atomic_cmpxchg(&g_links[i].is_used, 0, 1)) {
+ link = &g_links[i];
+ CAM_DBG(CAM_CRM, "alloc link index %d", i);
+ cam_req_mgr_core_link_reset(link);
+ break;
+ }
}
+ if (i == MAXIMUM_LINKS_PER_SESSION)
+ return NULL;
+
in_q = (struct cam_req_mgr_req_queue *)
kzalloc(sizeof(struct cam_req_mgr_req_queue), GFP_KERNEL);
if (!in_q) {
CAM_ERR(CAM_CRM, "failed to create input queue, no mem");
- kfree(link);
return NULL;
}
- mutex_init(&link->lock);
- spin_lock_init(&link->link_state_spin_lock);
mutex_lock(&link->lock);
- link->state = CAM_CRM_LINK_STATE_AVAILABLE;
link->num_devs = 0;
link->max_delay = 0;
memset(in_q->slot, 0,
@@ -1399,7 +1566,6 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link(
return link;
error:
mutex_unlock(&session->lock);
- kfree(link);
kfree(in_q);
return NULL;
}
@@ -1414,9 +1580,12 @@ error:
*/
static void __cam_req_mgr_free_link(struct cam_req_mgr_core_link *link)
{
+ ptrdiff_t i;
kfree(link->req.in_q);
link->req.in_q = NULL;
- kfree(link);
+ i = link - g_links;
+ CAM_DBG(CAM_CRM, "free link index %d", i);
+ atomic_set(&g_links[i].is_used, 0);
}
/**
@@ -1450,21 +1619,14 @@ static void __cam_req_mgr_unreserve_link(
for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
if (session->links[i] == link)
session->links[i] = NULL;
- }
- if ((session->sync_mode != CAM_REQ_MGR_SYNC_MODE_NO_SYNC) &&
- (link->sync_link)) {
- /*
- * make sure to unlink sync setup under the assumption
- * of only having 2 links in a given session
- */
- session->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC;
- for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
- if (session->links[i])
+ if (link->sync_link) {
+ if (link->sync_link == session->links[i])
session->links[i]->sync_link = NULL;
}
}
+ link->sync_link = NULL;
session->num_links--;
CAM_DBG(CAM_CRM, "Active session links (%d)", session->num_links);
mutex_unlock(&session->lock);
@@ -1544,6 +1706,9 @@ int cam_req_mgr_process_flush_req(void *priv, void *data)
mutex_lock(&link->req.lock);
if (flush_info->flush_type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
+ link->last_flush_id = flush_info->req_id;
+ CAM_INFO(CAM_CRM, "Last request id to flush is %lld",
+ flush_info->req_id);
for (i = 0; i < in_q->num_slots; i++) {
slot = &in_q->slot[i];
slot->req_id = -1;
@@ -1559,21 +1724,20 @@ int cam_req_mgr_process_flush_req(void *priv, void *data)
if (idx < 0) {
CAM_ERR(CAM_CRM, "req_id %lld not found in input queue",
flush_info->req_id);
- mutex_unlock(&link->req.lock);
- return -EINVAL;
- }
- CAM_DBG(CAM_CRM, "req_id %lld found at idx %d",
- flush_info->req_id, idx);
- slot = &in_q->slot[idx];
- if (slot->status == CRM_SLOT_STATUS_REQ_PENDING ||
- slot->status == CRM_SLOT_STATUS_REQ_APPLIED) {
- CAM_WARN(CAM_CRM,
- "req_id %lld can not be cancelled",
- flush_info->req_id);
- mutex_unlock(&link->req.lock);
- return -EINVAL;
+ } else {
+ CAM_DBG(CAM_CRM, "req_id %lld found at idx %d",
+ flush_info->req_id, idx);
+ slot = &in_q->slot[idx];
+ if (slot->status == CRM_SLOT_STATUS_REQ_PENDING ||
+ slot->status == CRM_SLOT_STATUS_REQ_APPLIED) {
+ CAM_WARN(CAM_CRM,
+ "req_id %lld can not be cancelled",
+ flush_info->req_id);
+ mutex_unlock(&link->req.lock);
+ return -EINVAL;
+ }
+ __cam_req_mgr_in_q_skip_idx(in_q, idx);
}
- __cam_req_mgr_in_q_skip_idx(in_q, idx);
}
for (i = 0; i < link->num_devs; i++) {
@@ -1622,9 +1786,11 @@ int cam_req_mgr_process_sched_req(void *priv, void *data)
sched_req = (struct cam_req_mgr_sched_request *)&task_data->u;
in_q = link->req.in_q;
- CAM_DBG(CAM_CRM, "link_hdl %x req_id %lld at slot %d sync_mode %d",
+ CAM_DBG(CAM_CRM,
+ "link_hdl %x req_id %lld at slot %d sync_mode %d is_master:%d",
sched_req->link_hdl, sched_req->req_id,
- in_q->wr_idx, sched_req->sync_mode);
+ in_q->wr_idx, sched_req->sync_mode,
+ link->is_master);
mutex_lock(&link->req.lock);
slot = &in_q->slot[in_q->wr_idx];
@@ -1640,6 +1806,16 @@ int cam_req_mgr_process_sched_req(void *priv, void *data)
slot->recover = sched_req->bubble_enable;
link->open_req_cnt++;
__cam_req_mgr_inc_idx(&in_q->wr_idx, 1, in_q->num_slots);
+
+ if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) {
+ if (link->initial_sync_req == -1)
+ link->initial_sync_req = slot->req_id;
+ } else {
+ link->initial_sync_req = -1;
+ if (link->sync_link)
+ link->sync_link->initial_sync_req = -1;
+ }
+
mutex_unlock(&link->req.lock);
end:
@@ -1736,8 +1912,9 @@ int cam_req_mgr_process_add_req(void *priv, void *data)
trace_cam_req_mgr_add_req(link, idx, add_req, tbl, device);
if (slot->req_ready_map == tbl->dev_mask) {
- CAM_DBG(CAM_REQ, "idx %d req_id %lld pd %d SLOT READY",
- idx, add_req->req_id, tbl->pd);
+ CAM_DBG(CAM_REQ,
+ "link 0x%x idx %d req_id %lld pd %d SLOT READY",
+ link->link_hdl, idx, add_req->req_id, tbl->pd);
slot->state = CRM_REQ_STATE_READY;
}
mutex_unlock(&link->req.lock);
@@ -1895,14 +2072,22 @@ static int cam_req_mgr_process_trigger(void *priv, void *data)
* Check if any new req is pending in slot, if not finish the
* lower pipeline delay device with available req ids.
*/
- CAM_DBG(CAM_CRM, "link[%x] Req[%lld] invalidating slot",
+ CAM_DBG(CAM_CRM, "link[%x] Req[%lld] invalidating slot",
link->link_hdl, in_q->slot[in_q->rd_idx].req_id);
- __cam_req_mgr_check_next_req_slot(in_q);
+ rc = __cam_req_mgr_check_next_req_slot(link);
+ if (rc) {
+ CAM_DBG(CAM_REQ,
+ "No pending req to apply to lower pd devices");
+ rc = 0;
+ goto release_lock;
+ }
__cam_req_mgr_inc_idx(&in_q->rd_idx, 1, in_q->num_slots);
}
+
rc = __cam_req_mgr_process_req(link, trigger_data->trigger);
- mutex_unlock(&link->req.lock);
+release_lock:
+ mutex_unlock(&link->req.lock);
end:
return rc;
}
@@ -2368,7 +2553,8 @@ static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link)
if (rc < 0) {
CAM_ERR(CAM_CRM, "error destroying link hdl %x rc %d",
link->link_hdl, rc);
- }
+ } else
+ link->link_hdl = -1;
mutex_unlock(&link->lock);
return rc;
@@ -2445,16 +2631,17 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
return -EINVAL;
}
+ mutex_lock(&g_crm_core_dev->crm_lock);
+
/* session hdl's priv data is cam session struct */
cam_session = (struct cam_req_mgr_core_session *)
cam_get_device_priv(link_info->session_hdl);
if (!cam_session) {
CAM_DBG(CAM_CRM, "NULL pointer");
+ mutex_unlock(&g_crm_core_dev->crm_lock);
return -EINVAL;
}
- mutex_lock(&g_crm_core_dev->crm_lock);
-
/* Allocate link struct and map it with session's request queue */
link = __cam_req_mgr_reserve_link(cam_session);
if (!link) {
@@ -2478,6 +2665,7 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
goto link_hdl_fail;
}
link_info->link_hdl = link->link_hdl;
+ link->last_flush_id = 0;
/* Allocate memory to hold data of all linked devs */
rc = __cam_req_mgr_create_subdevs(&link->l_dev,
@@ -2524,7 +2712,7 @@ setup_failed:
__cam_req_mgr_destroy_subdev(link->l_dev);
create_subdev_failed:
cam_destroy_device_hdl(link->link_hdl);
- link_info->link_hdl = 0;
+ link_info->link_hdl = -1;
link_hdl_fail:
mutex_unlock(&link->lock);
__cam_req_mgr_unreserve_link(cam_session, link);
@@ -2603,6 +2791,17 @@ int cam_req_mgr_schedule_request(
goto end;
}
+ if (sched_req->req_id <= link->last_flush_id) {
+ CAM_INFO(CAM_CRM,
+ "request %lld is flushed, last_flush_id to flush %d",
+ sched_req->req_id, link->last_flush_id);
+ rc = -EINVAL;
+ goto end;
+ }
+
+ if (sched_req->req_id > link->last_flush_id)
+ link->last_flush_id = 0;
+
CAM_DBG(CAM_CRM, "link 0x%x req %lld, sync_mode %d",
sched_req->link_hdl, sched_req->req_id, sched_req->sync_mode);
@@ -2627,6 +2826,33 @@ end:
return rc;
}
+/**
+ * __cam_req_mgr_set_master_link()
+ *
+ * @brief : Each links sets its max pd delay based on the devices on the
+ * link. The link with higher pd is assigned master.
+ * @link1 : One of the sync links
+ * @link2 : The other sync link
+ */
+static void __cam_req_mgr_set_master_link(
+ struct cam_req_mgr_core_link *link1,
+ struct cam_req_mgr_core_link *link2)
+{
+
+ if (link1->max_delay > link2->max_delay) {
+ link1->is_master = true;
+ link2->initial_skip = true;
+ } else if (link2->max_delay > link1->max_delay) {
+ link2->is_master = true;
+ link1->initial_skip = true;
+ }
+
+ CAM_DBG(CAM_CRM,
+ "link_hdl1[0x%x] is_master [%u] link_hdl2[0x%x] is_master[%u]",
+ link1->link_hdl, link1->is_master,
+ link2->link_hdl, link2->is_master);
+}
+
int cam_req_mgr_sync_config(
struct cam_req_mgr_sync_mode *sync_info)
{
@@ -2647,6 +2873,12 @@ int cam_req_mgr_sync_config(
return -EINVAL;
}
+ if ((sync_info->sync_mode != CAM_REQ_MGR_SYNC_MODE_SYNC) &&
+ (sync_info->sync_mode != CAM_REQ_MGR_SYNC_MODE_NO_SYNC)) {
+ CAM_ERR(CAM_CRM, "Invalid sync mode %d", sync_info->sync_mode);
+ return -EINVAL;
+ }
+
if ((!sync_info->link_hdls[0]) || (!sync_info->link_hdls[1])) {
CAM_WARN(CAM_CRM, "Invalid link handles 0x%x 0x%x",
sync_info->link_hdls[0], sync_info->link_hdls[1]);
@@ -2683,17 +2915,27 @@ int cam_req_mgr_sync_config(
goto done;
}
- link1->sof_counter = -1;
- link1->sync_self_ref = -1;
- link1->frame_skip_flag = false;
link1->sync_link_sof_skip = false;
- link1->sync_link = link2;
+ link1->sync_link = NULL;
- link2->sof_counter = -1;
- link2->sync_self_ref = -1;
- link2->frame_skip_flag = false;
link2->sync_link_sof_skip = false;
- link2->sync_link = link1;
+ link2->sync_link = NULL;
+
+ link1->is_master = false;
+ link2->is_master = false;
+ link1->initial_skip = false;
+ link2->initial_skip = false;
+
+ link1->in_msync_mode = false;
+ link2->in_msync_mode = false;
+ link1->initial_sync_req = -1;
+ link2->initial_sync_req = -1;
+
+ if (sync_info->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) {
+ link1->sync_link = link2;
+ link2->sync_link = link1;
+ __cam_req_mgr_set_master_link(link1, link2);
+ }
cam_session->sync_mode = sync_info->sync_mode;
CAM_DBG(CAM_REQ,
@@ -2791,7 +3033,8 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control)
goto end;
}
- if (control->num_links > MAX_LINKS_PER_SESSION) {
+ if ((control->num_links <= 0) ||
+ (control->num_links > MAX_LINKS_PER_SESSION)) {
CAM_ERR(CAM_CRM, "Invalid number of links %d",
control->num_links);
rc = -EINVAL;
@@ -2860,6 +3103,7 @@ end:
int cam_req_mgr_core_device_init(void)
{
+ int i;
CAM_DBG(CAM_CRM, "Enter g_crm_core_dev %pK", g_crm_core_dev);
if (g_crm_core_dev) {
@@ -2876,6 +3120,12 @@ int cam_req_mgr_core_device_init(void)
mutex_init(&g_crm_core_dev->crm_lock);
cam_req_mgr_debug_register(g_crm_core_dev);
+ for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
+ mutex_init(&g_links[i].lock);
+ spin_lock_init(&g_links[i].link_state_spin_lock);
+ atomic_set(&g_links[i].is_used, 0);
+ cam_req_mgr_core_link_reset(&g_links[i]);
+ }
return 0;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h
index b7222237473b..9bff66b36ebb 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, 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
@@ -135,9 +135,6 @@ enum cam_req_mgr_link_state {
* @apply_data : pointer which various tables will update during traverse
* @in_q : input request queue pointer
* @validate_only : Whether to validate only and/or update settings
- * @self_link : To indicate whether the check is for the given link or
- * the other sync link
- * @inject_delay_chk : if inject delay has been validated for all pd devices
* @open_req_cnt : Count of open requests yet to be serviced in the kernel.
*/
struct cam_req_mgr_traverse {
@@ -147,8 +144,6 @@ struct cam_req_mgr_traverse {
struct cam_req_mgr_apply *apply_data;
struct cam_req_mgr_req_queue *in_q;
bool validate_only;
- bool self_link;
- bool inject_delay_chk;
int32_t open_req_cnt;
};
@@ -308,15 +303,20 @@ struct cam_req_mgr_connected_device {
* notification to CRM at those hw events.
* @trigger_mask : mask on which irq the req is already applied
* @sync_link : pointer to the sync link for synchronization
- * @sof_counter : sof counter during sync_mode
- * @sync_self_ref : reference sync count against which the difference
- * between sync_counts for a given link is checked
- * @frame_skip_flag : flag that determines if a frame needs to be skipped
* @sync_link_sof_skip : flag determines if a pkt is not available for a given
* frame in a particular link skip corresponding
* frame in sync link as well.
* @open_req_cnt : Counter to keep track of open requests that are yet
* to be serviced in the kernel.
+ * @last_flush_id : Last request to flush
+ * @is_used : 1 if link is in use else 0
+ * @is_master : Based on pd among links, the link with the highest pd
+ * is assigned as master
+ * @initial_skip : Flag to determine if slave has started streaming in
+ * master-slave sync
+ * @in_msync_mode : Flag to determine if a link is in master-slave mode
+ * @initial_sync_req : The initial req which is required to sync with the
+ * other link
*
*/
struct cam_req_mgr_core_link {
@@ -336,11 +336,14 @@ struct cam_req_mgr_core_link {
uint32_t subscribe_event;
uint32_t trigger_mask;
struct cam_req_mgr_core_link *sync_link;
- int64_t sof_counter;
- int64_t sync_self_ref;
- bool frame_skip_flag;
bool sync_link_sof_skip;
int32_t open_req_cnt;
+ uint32_t last_flush_id;
+ atomic_t is_used;
+ bool is_master;
+ bool initial_skip;
+ bool in_msync_mode;
+ int64_t initial_sync_req;
};
/**
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h
index 1df3122109e6..1d1df45c6ea5 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, 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
@@ -50,7 +50,7 @@ typedef int (*cam_req_mgr_add_req)(struct cam_req_mgr_add_request *);
* @cam_req_mgr_link_setup : to establish link with device for a session
* @cam_req_mgr_notify_err : to broadcast error happened on link for request id
* @cam_req_mgr_apply_req : CRM asks device to apply certain request id.
- * @cam_req_mgr_flush_req : Flush or cancle request
+ * @cam_req_mgr_flush_req : Flush or cancel request
* cam_req_mgr_process_evt : generic events
*/
typedef int (*cam_req_mgr_get_dev_info) (struct cam_req_mgr_device_info *);
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.c b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.c
index 12bc3ac47a8e..de6a2dc519df 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.c
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, 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
@@ -224,8 +224,8 @@ int cam_req_mgr_workq_create(char *name, int32_t num_tasks,
crm_workq->in_irq = in_irq;
crm_workq->task.num_task = num_tasks;
crm_workq->task.pool = (struct crm_workq_task *)
- kzalloc(sizeof(struct crm_workq_task) *
- crm_workq->task.num_task,
+ kcalloc(crm_workq->task.num_task,
+ sizeof(struct crm_workq_task),
GFP_KERNEL);
if (!crm_workq->task.pool) {
CAM_WARN(CAM_CRM, "Insufficient memory %zu",
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.h b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.h
index af76ae467346..c24ee31959d6 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.h
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, 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
@@ -26,7 +26,8 @@
/* Flag to create a high priority workq */
#define CAM_WORKQ_FLAG_HIGH_PRIORITY (1 << 0)
-/* This flag ensures only one task from a given
+/*
+ * This flag ensures only one task from a given
* workq will execute at any given point on any
* given CPU.
*/
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c
index b2a7dc0784f4..1262db7646dc 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -17,6 +17,7 @@
#include "cam_trace.h"
#include "cam_res_mgr_api.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
int32_t cam_actuator_construct_default_power_setting(
struct cam_sensor_power_ctrl_t *power_info)
@@ -214,12 +215,12 @@ static int32_t cam_actuator_i2c_modes_util(
}
int32_t cam_actuator_slaveInfo_pkt_parser(struct cam_actuator_ctrl_t *a_ctrl,
- uint32_t *cmd_buf)
+ uint32_t *cmd_buf, size_t len)
{
int32_t rc = 0;
struct cam_cmd_i2c_info *i2c_info;
- if (!a_ctrl || !cmd_buf) {
+ if (!a_ctrl || !cmd_buf || (len < sizeof(struct cam_cmd_i2c_info))) {
CAM_ERR(CAM_ACTUATOR, "Invalid Args");
return -EINVAL;
}
@@ -413,9 +414,11 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
int32_t i = 0;
uint32_t total_cmd_buf_in_bytes = 0;
size_t len_of_buff = 0;
+ size_t remain_len = 0;
uint32_t *offset = NULL;
uint32_t *cmd_buf = NULL;
uintptr_t generic_ptr;
+ uintptr_t generic_pkt_ptr;
struct common_header *cmm_hdr = NULL;
struct cam_control *ioctl_ctrl = NULL;
struct cam_packet *csl_packet = NULL;
@@ -442,23 +445,36 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
sizeof(config)))
return -EFAULT;
rc = cam_mem_get_cpu_buf(config.packet_handle,
- &generic_ptr, &len_of_buff);
+ &generic_pkt_ptr, &len_of_buff);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR, "Error in converting command Handle %d",
rc);
return rc;
}
- if (config.offset > len_of_buff) {
+ remain_len = len_of_buff;
+ if ((sizeof(struct cam_packet) > len_of_buff) ||
+ ((size_t)config.offset >= len_of_buff -
+ sizeof(struct cam_packet))) {
CAM_ERR(CAM_ACTUATOR,
- "offset is out of bounds: offset: %lld len: %zu",
- config.offset, len_of_buff);
- return -EINVAL;
+ "Inval cam_packet strut size: %zu, len_of_buff: %zu",
+ sizeof(struct cam_packet), len_of_buff);
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
- csl_packet =
- (struct cam_packet *)(generic_ptr + (uint32_t)config.offset);
- CAM_DBG(CAM_ACTUATOR, "Pkt opcode: %d", csl_packet->header.op_code);
+ remain_len -= (size_t)config.offset;
+ csl_packet = (struct cam_packet *)
+ (generic_pkt_ptr + (uint32_t)config.offset);
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_ACTUATOR, "Invalid packet params");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+
+ CAM_DBG(CAM_ACTUATOR, "Pkt opcode: %d", csl_packet->header.op_code);
if ((csl_packet->header.op_code & 0xFFFFFF) !=
CAM_ACTUATOR_PACKET_OPCODE_INIT &&
@@ -467,7 +483,8 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
CAM_DBG(CAM_ACTUATOR,
"reject request %lld, last request to flush %lld",
csl_packet->header.request_id, a_ctrl->last_flush_req);
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
if (csl_packet->header.request_id > a_ctrl->last_flush_req)
@@ -488,13 +505,22 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
&generic_ptr, &len_of_buff);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR, "Failed to get cpu buf");
- return rc;
+ goto rel_pkt_buf;
}
cmd_buf = (uint32_t *)generic_ptr;
if (!cmd_buf) {
CAM_ERR(CAM_ACTUATOR, "invalid cmd buf");
- return -EINVAL;
+ goto rel_cmd_buf;
+ }
+ if ((len_of_buff < sizeof(struct common_header)) ||
+ (cmd_desc[i].offset > (len_of_buff -
+ sizeof(struct common_header)))) {
+ CAM_ERR(CAM_ACTUATOR,
+ "Invalid length for sensor cmd");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
+ remain_len = len_of_buff - cmd_desc[i].offset;
cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
cmm_hdr = (struct common_header *)cmd_buf;
@@ -503,11 +529,11 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
CAM_DBG(CAM_ACTUATOR,
"Received slave info buffer");
rc = cam_actuator_slaveInfo_pkt_parser(
- a_ctrl, cmd_buf);
+ a_ctrl, cmd_buf, remain_len);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Failed to parse slave info: %d", rc);
- return rc;
+ goto rel_cmd_buf;
}
break;
case CAMERA_SENSOR_CMD_TYPE_PWR_UP:
@@ -517,12 +543,12 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
rc = cam_sensor_update_power_settings(
cmd_buf,
total_cmd_buf_in_bytes,
- power_info);
+ power_info, remain_len);
if (rc) {
CAM_ERR(CAM_ACTUATOR,
"Failed:parse power settings: %d",
rc);
- return rc;
+ goto rel_cmd_buf;
}
break;
default:
@@ -542,10 +568,14 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
CAM_ERR(CAM_ACTUATOR,
"Failed:parse init settings: %d",
rc);
- return rc;
+ goto rel_cmd_buf;
}
break;
}
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_ACTUATOR,
+ "Failed to put cpu buf: %d",
+ cmd_desc[i].mem_handle);
}
if (a_ctrl->cam_act_state == CAM_ACTUATOR_ACQUIRE) {
@@ -553,7 +583,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
" Actuator Power up failed");
- return rc;
+ goto rel_pkt_buf;
}
a_ctrl->cam_act_state = CAM_ACTUATOR_CONFIG;
}
@@ -562,7 +592,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
&a_ctrl->i2c_data.init_settings);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR, "Cannot apply Init settings");
- return rc;
+ goto rel_pkt_buf;
}
/* Delete the request even if the apply is failed */
@@ -579,7 +609,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
CAM_WARN(CAM_ACTUATOR,
"Not in right state to move lens: %d",
a_ctrl->cam_act_state);
- return rc;
+ goto rel_pkt_buf;
}
a_ctrl->setting_apply_state = ACT_APPLY_SETTINGS_NOW;
@@ -599,7 +629,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Auto move lens parsing failed: %d", rc);
- return rc;
+ goto rel_pkt_buf;
}
cam_actuator_update_req_mgr(a_ctrl, csl_packet);
break;
@@ -609,7 +639,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
CAM_WARN(CAM_ACTUATOR,
"Not in right state to move lens: %d",
a_ctrl->cam_act_state);
- return rc;
+ goto rel_pkt_buf;
}
a_ctrl->setting_apply_state = ACT_APPLY_SETTINGS_LATER;
@@ -630,7 +660,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Manual move lens parsing failed: %d", rc);
- return rc;
+ goto rel_pkt_buf;
}
cam_actuator_update_req_mgr(a_ctrl, csl_packet);
@@ -640,13 +670,32 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
CAM_WARN(CAM_ACTUATOR,
"Received NOP packets in invalid state: %d",
a_ctrl->cam_act_state);
- return -EINVAL;
+ goto rel_pkt_buf;
}
-
cam_actuator_update_req_mgr(a_ctrl, csl_packet);
break;
+ default:
+ CAM_ERR(CAM_ACTUATOR, "Wrong Opcode: %d",
+ csl_packet->header.op_code & 0xFFFFFF);
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
+ if (cam_mem_put_cpu_buf(config.packet_handle))
+ CAM_WARN(CAM_ACTUATOR, "Fail to put cmd buffer: %llu",
+ config.packet_handle);
+
+ return rc;
+
+rel_cmd_buf:
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_ACTUATOR, "Fail to put cmd buffer: %d",
+ cmd_desc[i].mem_handle);
+rel_pkt_buf:
+ if (cam_mem_put_cpu_buf(config.packet_handle))
+ CAM_WARN(CAM_ACTUATOR, "Fail to put cmd buffer: %llu",
+ config.packet_handle);
+
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_dev.c
index 26d73a446a5b..228ccb8a39b3 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -216,9 +216,7 @@ static int32_t cam_actuator_driver_i2c_probe(struct i2c_client *client,
cam_actuator_establish_link;
a_ctrl->bridge_intf.ops.apply_req =
cam_actuator_apply_request;
-
- v4l2_set_subdevdata(&(a_ctrl->v4l2_dev_str.sd), a_ctrl);
-
+ a_ctrl->last_flush_req = 0;
a_ctrl->cam_act_state = CAM_ACTUATOR_INIT;
return rc;
@@ -245,19 +243,24 @@ static int32_t cam_actuator_platform_remove(struct platform_device *pdev)
return 0;
}
+ CAM_INFO(CAM_ACTUATOR, "platform remove invoked");
+ mutex_lock(&(a_ctrl->actuator_mutex));
+ cam_actuator_shutdown(a_ctrl);
+ mutex_unlock(&(a_ctrl->actuator_mutex));
+ cam_unregister_subdev(&(a_ctrl->v4l2_dev_str));
+
soc_private =
(struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private;
power_info = &soc_private->power_info;
kfree(a_ctrl->io_master_info.cci_client);
a_ctrl->io_master_info.cci_client = NULL;
- kfree(power_info->power_setting);
- kfree(power_info->power_down_setting);
- power_info->power_setting = NULL;
- power_info->power_down_setting = NULL;
kfree(a_ctrl->soc_info.soc_private);
+ a_ctrl->soc_info.soc_private = NULL;
kfree(a_ctrl->i2c_data.per_frame);
a_ctrl->i2c_data.per_frame = NULL;
+ v4l2_set_subdevdata(&a_ctrl->v4l2_dev_str.sd, NULL);
+ platform_set_drvdata(pdev, NULL);
devm_kfree(&pdev->dev, a_ctrl);
return rc;
@@ -265,7 +268,6 @@ static int32_t cam_actuator_platform_remove(struct platform_device *pdev)
static int32_t cam_actuator_driver_i2c_remove(struct i2c_client *client)
{
- int32_t rc = 0;
struct cam_actuator_ctrl_t *a_ctrl =
i2c_get_clientdata(client);
struct cam_actuator_soc_private *soc_private;
@@ -277,6 +279,11 @@ static int32_t cam_actuator_driver_i2c_remove(struct i2c_client *client)
return -EINVAL;
}
+ CAM_INFO(CAM_ACTUATOR, "i2c remove invoked");
+ mutex_lock(&(a_ctrl->actuator_mutex));
+ cam_actuator_shutdown(a_ctrl);
+ mutex_unlock(&(a_ctrl->actuator_mutex));
+ cam_unregister_subdev(&(a_ctrl->v4l2_dev_str));
soc_private =
(struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private;
power_info = &soc_private->power_info;
@@ -284,14 +291,11 @@ static int32_t cam_actuator_driver_i2c_remove(struct i2c_client *client)
/*Free Allocated Mem */
kfree(a_ctrl->i2c_data.per_frame);
a_ctrl->i2c_data.per_frame = NULL;
- kfree(power_info->power_setting);
- kfree(power_info->power_down_setting);
- kfree(a_ctrl->soc_info.soc_private);
- power_info->power_setting = NULL;
- power_info->power_down_setting = NULL;
a_ctrl->soc_info.soc_private = NULL;
+ v4l2_set_subdevdata(&a_ctrl->v4l2_dev_str.sd, NULL);
kfree(a_ctrl);
- return rc;
+
+ return 0;
}
static const struct of_device_id cam_actuator_driver_dt_match[] = {
@@ -376,7 +380,6 @@ static int32_t cam_actuator_driver_platform_probe(
a_ctrl->last_flush_req = 0;
platform_set_drvdata(pdev, a_ctrl);
- v4l2_set_subdevdata(&a_ctrl->v4l2_dev_str.sd, a_ctrl);
a_ctrl->cam_act_state = CAM_ACTUATOR_INIT;
return rc;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_core.c
index b0e810711c5d..f41cb4753f39 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -892,20 +892,39 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
soc_info = &cci_dev->soc_info;
base = soc_info->reg_map[0].mem_base;
- mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
- /*
- * Todo: If there is a change in frequency of operation
- * Wait for previos transaction to complete
- */
+ mutex_lock(&cci_dev->cci_master_info[master].mutex);
+ if (cci_dev->cci_master_info[master].is_first_req == true) {
+ cci_dev->cci_master_info[master].is_first_req = false;
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ down(&cci_dev->cci_master_info[master].master_sem);
+ } else if (c_ctrl->cci_info->i2c_freq_mode
+ != cci_dev->i2c_freq_mode[master]) {
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ down(&cci_dev->cci_master_info[master].master_sem);
+ } else {
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+ cci_dev->cci_master_info[master].freq_ref_cnt++;
+ spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
+ }
/* Set the I2C Frequency */
rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
if (rc < 0) {
CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
- goto rel_mutex;
+ mutex_unlock(&cci_dev->cci_master_info[master].mutex);
+ goto rel_master;
}
+ mutex_unlock(&cci_dev->cci_master_info[master].mutex);
+ mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
/*
* Call validate queue to make sure queue is empty before starting.
* If this call fails, don't proceed with i2c_read call. This is to
@@ -916,24 +935,24 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
master, queue);
if (rc < 0) {
CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
CAM_ERR(CAM_CCI, "More than max retries");
- goto rel_mutex;
+ goto rel_mutex_q;
}
if (read_cfg->data == NULL) {
CAM_ERR(CAM_CCI, "Data ptr is NULL");
- goto rel_mutex;
+ goto rel_mutex_q;
}
if (read_cfg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
CAM_ERR(CAM_CCI, "failed : Invalid addr type: %u",
read_cfg->addr_type);
rc = -EINVAL;
- goto rel_mutex;
+ goto rel_mutex_q;
}
CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d",
@@ -945,14 +964,14 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = CCI_I2C_LOCK_CMD;
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = CCI_I2C_WRITE_DISABLE_P_CMD | (read_cfg->addr_type << 4);
@@ -964,21 +983,21 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = CCI_I2C_READ_CMD | (read_cfg->num_byte << 4);
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = CCI_I2C_UNLOCK_CMD;
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR
@@ -1009,7 +1028,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
cam_cci_dump_registers(cci_dev, master, queue);
#endif
cam_cci_flush_queue(cci_dev, master);
- goto rel_mutex;
+ goto rel_mutex_q;
}
read_words = cam_io_r_mb(base +
@@ -1090,7 +1109,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
master, queue);
#endif
cam_cci_flush_queue(cci_dev, master);
- goto rel_mutex;
+ goto rel_mutex_q;
}
break;
}
@@ -1099,8 +1118,15 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
CAM_DBG(CAM_CCI, "Burst read successful words_read %d",
total_read_words);
-rel_mutex:
+rel_mutex_q:
mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);
+rel_master:
+ spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+ if (cci_dev->cci_master_info[master].freq_ref_cnt == 0)
+ up(&cci_dev->cci_master_info[master].master_sem);
+ else
+ cci_dev->cci_master_info[master].freq_ref_cnt--;
+ spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
return rc;
}
@@ -1132,20 +1158,38 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
soc_info = &cci_dev->soc_info;
base = soc_info->reg_map[0].mem_base;
- mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
-
- /*
- * Todo: If there is a change in frequency of operation
- * Wait for previos transaction to complete
- */
+ mutex_lock(&cci_dev->cci_master_info[master].mutex);
+ if (cci_dev->cci_master_info[master].is_first_req == true) {
+ cci_dev->cci_master_info[master].is_first_req = false;
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ down(&cci_dev->cci_master_info[master].master_sem);
+ } else if (c_ctrl->cci_info->i2c_freq_mode
+ != cci_dev->i2c_freq_mode[master]) {
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ down(&cci_dev->cci_master_info[master].master_sem);
+ } else {
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+ cci_dev->cci_master_info[master].freq_ref_cnt++;
+ spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
+ }
/* Set the I2C Frequency */
rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
if (rc < 0) {
+ mutex_unlock(&cci_dev->cci_master_info[master].mutex);
CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
- goto rel_mutex;
+ goto rel_master;
}
+ mutex_unlock(&cci_dev->cci_master_info[master].mutex);
+ mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
/*
* Call validate queue to make sure queue is empty before starting.
* If this call fails, don't proceed with i2c_read call. This is to
@@ -1156,17 +1200,17 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
master, queue);
if (rc < 0) {
CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
CAM_ERR(CAM_CCI, "More than max retries");
- goto rel_mutex;
+ goto rel_mutex_q;
}
if (read_cfg->data == NULL) {
CAM_ERR(CAM_CCI, "Data ptr is NULL");
- goto rel_mutex;
+ goto rel_mutex_q;
}
CAM_DBG(CAM_CCI, "master %d, queue %d", master, queue);
@@ -1179,21 +1223,21 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = CCI_I2C_LOCK_CMD;
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
if (read_cfg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
CAM_ERR(CAM_CCI, "failed : Invalid addr type: %u",
read_cfg->addr_type);
rc = -EINVAL;
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = CCI_I2C_WRITE_DISABLE_P_CMD | (read_cfg->addr_type << 4);
@@ -1205,21 +1249,21 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = CCI_I2C_READ_CMD | (read_cfg->num_byte << 4);
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = CCI_I2C_UNLOCK_CMD;
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR
@@ -1247,7 +1291,7 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
"wait_for_completion_timeout rc = %d FIFO buf_lvl: 0x%x",
rc, val);
cam_cci_flush_queue(cci_dev, master);
- goto rel_mutex;
+ goto rel_mutex_q;
} else {
rc = 0;
}
@@ -1260,7 +1304,7 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
read_words, exp_words);
memset(read_cfg->data, 0, read_cfg->num_byte);
rc = -EINVAL;
- goto rel_mutex;
+ goto rel_mutex_q;
}
index = 0;
CAM_DBG(CAM_CCI, "index %d num_type %d", index, read_cfg->num_byte);
@@ -1284,8 +1328,15 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
}
read_words--;
}
-rel_mutex:
+rel_mutex_q:
mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);
+rel_master:
+ spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+ if (cci_dev->cci_master_info[master].freq_ref_cnt == 0)
+ up(&cci_dev->cci_master_info[master].master_sem);
+ else
+ cci_dev->cci_master_info[master].freq_ref_cnt--;
+ spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
return rc;
}
@@ -1309,12 +1360,36 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
c_ctrl->cci_info->id_map);
+ mutex_lock(&cci_dev->cci_master_info[master].mutex);
+ if (cci_dev->cci_master_info[master].is_first_req == true) {
+ cci_dev->cci_master_info[master].is_first_req = false;
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ down(&cci_dev->cci_master_info[master].master_sem);
+ } else if (c_ctrl->cci_info->i2c_freq_mode
+ != cci_dev->i2c_freq_mode[master]) {
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ down(&cci_dev->cci_master_info[master].master_sem);
+ } else {
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+ cci_dev->cci_master_info[master].freq_ref_cnt++;
+ spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
+ }
+
/* Set the I2C Frequency */
rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
if (rc < 0) {
CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
- return rc;
+ mutex_unlock(&cci_dev->cci_master_info[master].mutex);
+ goto ERROR;
}
+ mutex_unlock(&cci_dev->cci_master_info[master].mutex);
/*
* Call validate queue to make sure queue is empty before starting.
* If this call fails, don't proceed with i2c_write call. This is to
@@ -1326,18 +1401,25 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
if (rc < 0) {
CAM_ERR(CAM_CCI, "Initial validataion failed rc %d",
rc);
- return rc;
+ goto ERROR;
}
if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
CAM_ERR(CAM_CCI, "More than max retries");
- return rc;
+ goto ERROR;
}
rc = cam_cci_data_queue(cci_dev, c_ctrl, queue, sync_en);
if (rc < 0) {
CAM_ERR(CAM_CCI, "failed rc: %d", rc);
- return rc;
+ goto ERROR;
}
+ERROR:
+ spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+ if (cci_dev->cci_master_info[master].freq_ref_cnt == 0)
+ up(&cci_dev->cci_master_info[master].master_sem);
+ else
+ cci_dev->cci_master_info[master].freq_ref_cnt--;
+ spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.c
index 5e522a8a5959..7934aa50767c 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -151,7 +151,6 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
complete(&cci_dev->cci_master_info[MASTER_1].th_complete);
complete(&cci_dev->cci_master_info[MASTER_1].reset_complete);
}
- rd_done_th_assert = false;
if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) &&
(!rd_done_th_assert)) {
cci_dev->cci_master_info[MASTER_1].status = 0;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.h
index 12abeabe0a38..349effcc057b 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -26,6 +26,7 @@
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
+#include <linux/semaphore.h>
#include <media/cam_sensor.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
@@ -144,6 +145,10 @@ struct cam_cci_master_info {
struct completion report_q[NUM_QUEUES];
atomic_t done_pending[NUM_QUEUES];
spinlock_t lock_q[NUM_QUEUES];
+ spinlock_t freq_cnt;
+ struct semaphore master_sem;
+ bool is_first_req;
+ uint16_t freq_ref_cnt;
};
struct cam_cci_clk_params_t {
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c
index da714af3fde2..7d71cd57573e 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -196,7 +196,10 @@ static void cam_cci_init_cci_params(struct cci_device *new_cci_dev)
for (i = 0; i < NUM_MASTERS; i++) {
new_cci_dev->cci_master_info[i].status = 0;
+ new_cci_dev->cci_master_info[i].is_first_req = true;
mutex_init(&new_cci_dev->cci_master_info[i].mutex);
+ sema_init(&new_cci_dev->cci_master_info[i].master_sem, 1);
+ spin_lock_init(&new_cci_dev->cci_master_info[i].freq_cnt);
init_completion(
&new_cci_dev->cci_master_info[i].reset_complete);
init_completion(
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
index 9894b217ac2c..17499489184b 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -15,6 +15,8 @@
#include "cam_csiphy_dev.h"
#include "cam_csiphy_soc.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
+
#include <soc/qcom/scm.h>
#include <cam_mem_mgr.h>
@@ -159,11 +161,13 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
{
int32_t rc = 0;
uintptr_t generic_ptr;
+ uintptr_t generic_pkt_ptr;
struct cam_packet *csl_packet = NULL;
struct cam_cmd_buf_desc *cmd_desc = NULL;
uint32_t *cmd_buf = NULL;
struct cam_csiphy_info *cam_cmd_csiphy_info = NULL;
size_t len;
+ size_t remain_len;
if (!cfg_dev || !csiphy_dev) {
CAM_ERR(CAM_CSIPHY, "Invalid Args");
@@ -171,21 +175,32 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
}
rc = cam_mem_get_cpu_buf((int32_t) cfg_dev->packet_handle,
- &generic_ptr, &len);
+ &generic_pkt_ptr, &len);
if (rc < 0) {
CAM_ERR(CAM_CSIPHY, "Failed to get packet Mem address: %d", rc);
return rc;
}
- if (cfg_dev->offset > len) {
+ remain_len = len;
+ if ((sizeof(struct cam_packet) > len) ||
+ ((size_t)cfg_dev->offset >= len - sizeof(struct cam_packet))) {
CAM_ERR(CAM_CSIPHY,
- "offset is out of bounds: offset: %lld len: %zu",
- cfg_dev->offset, len);
- return -EINVAL;
+ "Inval cam_packet strut size: %zu, len_of_buff: %zu",
+ sizeof(struct cam_packet), len);
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
+ remain_len -= (size_t)cfg_dev->offset;
csl_packet = (struct cam_packet *)
- (generic_ptr + (uint32_t)cfg_dev->offset);
+ (generic_pkt_ptr + (uint32_t)cfg_dev->offset);
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_CSIPHY, "Invalid packet params");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
cmd_desc = (struct cam_cmd_buf_desc *)
((uint32_t *)&csl_packet->payload +
@@ -196,7 +211,15 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
if (rc < 0) {
CAM_ERR(CAM_CSIPHY,
"Failed to get cmd buf Mem address : %d", rc);
- return rc;
+ goto rel_pkt_buf;
+ }
+
+ if ((len < sizeof(struct cam_csiphy_info)) ||
+ (cmd_desc->offset > (len - sizeof(struct cam_csiphy_info)))) {
+ CAM_ERR(CAM_CSIPHY,
+ "Not enough buffer provided for cam_cisphy_info");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
cmd_buf = (uint32_t *)generic_ptr;
@@ -221,6 +244,15 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
cam_csiphy_update_secure_info(csiphy_dev,
cam_cmd_csiphy_info, cfg_dev);
+ if (cam_mem_put_cpu_buf(cmd_desc->mem_handle))
+ CAM_WARN(CAM_CSIPHY, "Failed to put cmd buffer: %d",
+ cmd_desc->mem_handle);
+
+rel_pkt_buf:
+ if (cam_mem_put_cpu_buf((int32_t) cfg_dev->packet_handle))
+ CAM_WARN(CAM_CSIPHY, "Failed to put packet Mem address: %llu",
+ cfg_dev->packet_handle);
+
return rc;
}
@@ -567,6 +599,14 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
struct cam_create_dev_hdl bridge_params;
+ if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) {
+ CAM_ERR(CAM_CSIPHY,
+ "Not in right state to acquire : %d",
+ csiphy_dev->csiphy_state);
+ rc = -EINVAL;
+ goto release_mutex;
+ }
+
rc = copy_from_user(&csiphy_acq_dev,
u64_to_user_ptr(cmd->handle),
sizeof(csiphy_acq_dev));
@@ -826,6 +866,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
if (rc < 0) {
csiphy_dev->csiphy_info.secure_mode[offset] =
CAM_SECURE_MODE_NON_SECURE;
+ cam_cpas_stop(csiphy_dev->cpas_handle);
goto release_mutex;
}
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c
index 32bb34bb257b..972b0a549f30 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -165,7 +165,6 @@ static int32_t cam_csiphy_platform_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, &(new_csiphy_dev->v4l2_dev_str.sd));
- v4l2_set_subdevdata(&(new_csiphy_dev->v4l2_dev_str.sd), new_csiphy_dev);
new_csiphy_dev->bridge_intf.device_hdl[0] = -1;
new_csiphy_dev->bridge_intf.device_hdl[1] = -1;
@@ -211,9 +210,17 @@ static int32_t cam_csiphy_device_remove(struct platform_device *pdev)
struct csiphy_device *csiphy_dev =
v4l2_get_subdevdata(subdev);
+ CAM_INFO(CAM_CSIPHY, "device remove invoked");
cam_cpas_unregister_client(csiphy_dev->cpas_handle);
cam_csiphy_soc_release(csiphy_dev);
+ mutex_lock(&csiphy_dev->mutex);
+ cam_csiphy_shutdown(csiphy_dev);
+ mutex_unlock(&csiphy_dev->mutex);
+ cam_unregister_subdev(&(csiphy_dev->v4l2_dev_str));
kfree(csiphy_dev->ctrl_reg);
+ csiphy_dev->ctrl_reg = NULL;
+ platform_set_drvdata(pdev, NULL);
+ v4l2_set_subdevdata(&(csiphy_dev->v4l2_dev_str.sd), NULL);
devm_kfree(&pdev->dev, csiphy_dev);
return 0;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
index a16fb888edc6..945910e96a55 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, 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
@@ -20,7 +20,7 @@ struct csiphy_reg_parms_t csiphy_v1_2 = {
.mipi_csiphy_interrupt_clear0_addr = 0x858,
.mipi_csiphy_glbl_irq_cmd_addr = 0x828,
.csiphy_common_array_size = 4,
- .csiphy_reset_array_size = 4,
+ .csiphy_reset_array_size = 5,
.csiphy_2ph_config_array_size = 21,
.csiphy_3ph_config_array_size = 31,
.csiphy_2ph_clock_lane = 0x1,
@@ -38,6 +38,7 @@ struct csiphy_reg_t csiphy_reset_reg_1_2[] = {
{0x0814, 0x00, 0x05, CSIPHY_LANE_ENABLE},
{0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h
index 8d7a5b58215a..b7345d4abeeb 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, 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
@@ -19,8 +19,8 @@ struct csiphy_reg_parms_t csiphy_v2_0 = {
.mipi_csiphy_interrupt_status0_addr = 0x8B0,
.mipi_csiphy_interrupt_clear0_addr = 0x858,
.mipi_csiphy_glbl_irq_cmd_addr = 0x828,
- .csiphy_common_array_size = 6,
- .csiphy_reset_array_size = 3,
+ .csiphy_common_array_size = 8,
+ .csiphy_reset_array_size = 5,
.csiphy_2ph_config_array_size = 15,
.csiphy_3ph_config_array_size = 17,
.csiphy_2ph_clock_lane = 0x1,
@@ -31,6 +31,8 @@ struct csiphy_reg_t csiphy_common_reg_2_0[] = {
{0x0814, 0x00, 0x00, CSIPHY_LANE_ENABLE},
{0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x081C, 0x06, 0x00, CSIPHY_3PH_REGS},
+ {0x0800, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0164, 0x00, 0x00, CSIPHY_2PH_REGS},
{0x0364, 0x00, 0x00, CSIPHY_2PH_REGS},
{0x0564, 0x00, 0x00, CSIPHY_2PH_REGS},
@@ -40,6 +42,8 @@ struct csiphy_reg_t csiphy_reset_reg_2_0[] = {
{0x0814, 0x00, 0x05, CSIPHY_LANE_ENABLE},
{0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
};
struct csiphy_reg_t csiphy_irq_reg_2_0[] = {
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
index 7d7c1a2977e5..220cd1598922 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -18,6 +18,7 @@
#include "cam_eeprom_soc.h"
#include "cam_debug_util.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
/**
* cam_eeprom_read_memory() - read map data into buffer
@@ -413,7 +414,7 @@ static int32_t cam_eeprom_update_slaveInfo(struct cam_eeprom_ctrl_t *e_ctrl,
static int32_t cam_eeprom_parse_memory_map(
struct cam_eeprom_memory_block_t *data,
void *cmd_buf, int cmd_length, uint16_t *cmd_length_bytes,
- int *num_map)
+ int *num_map, size_t remain_buf_len)
{
int32_t rc = 0;
int32_t cnt = 0;
@@ -427,8 +428,21 @@ static int32_t cam_eeprom_parse_memory_map(
struct cam_cmd_i2c_continuous_rd *i2c_cont_rd = NULL;
struct cam_cmd_conditional_wait *i2c_poll = NULL;
struct cam_cmd_unconditional_wait *i2c_uncond_wait = NULL;
+ size_t validate_size = 0;
generic_op_code = cmm_hdr->third_byte;
+
+ if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR)
+ validate_size = sizeof(struct cam_cmd_i2c_random_wr);
+ else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD)
+ validate_size = sizeof(struct cam_cmd_i2c_continuous_rd);
+ else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT)
+ validate_size = sizeof(struct cam_cmd_unconditional_wait);
+
+ if (remain_buf_len < validate_size) {
+ CAM_ERR(CAM_EEPROM, "not enough buffer");
+ return -EINVAL;
+ }
switch (cmm_hdr->cmd_type) {
case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR:
i2c_random_wr = (struct cam_cmd_i2c_random_wr *)cmd_buf;
@@ -535,6 +549,7 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
uint32_t *cmd_buf = NULL;
uintptr_t generic_pkt_addr;
size_t pkt_len = 0;
+ size_t remain_len = 0;
uint32_t total_cmd_buf_in_bytes = 0;
uint32_t processed_cmd_buf_in_bytes = 0;
struct common_header *cmm_hdr = NULL;
@@ -575,15 +590,43 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
cmd_buf = (uint32_t *)generic_pkt_addr;
if (!cmd_buf) {
CAM_ERR(CAM_EEPROM, "invalid cmd buf");
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
+
+ if ((pkt_len < sizeof(struct common_header)) ||
+ (cmd_desc[i].offset > (pkt_len -
+ sizeof(struct common_header)))) {
+ CAM_ERR(CAM_EEPROM, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+ remain_len = pkt_len - cmd_desc[i].offset;
cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
+
+ if (total_cmd_buf_in_bytes > remain_len) {
+ CAM_ERR(CAM_EEPROM, "Not enough buffer for command");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
/* Loop through multiple cmd formats in one cmd buffer */
while (processed_cmd_buf_in_bytes < total_cmd_buf_in_bytes) {
+ if ((remain_len - processed_cmd_buf_in_bytes) <
+ sizeof(struct common_header)) {
+ CAM_ERR(CAM_EEPROM, "Not enough buf");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
cmm_hdr = (struct common_header *)cmd_buf;
switch (cmm_hdr->cmd_type) {
case CAMERA_SENSOR_CMD_TYPE_I2C_INFO:
i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
+ if ((remain_len - processed_cmd_buf_in_bytes) <
+ sizeof(struct cam_cmd_i2c_info)) {
+ CAM_ERR(CAM_EEPROM, "Not enough buf");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
/* Configure the following map slave address */
map[num_map + 1].saddr = i2c_info->slave_addr;
rc = cam_eeprom_update_slaveInfo(e_ctrl,
@@ -599,14 +642,16 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
case CAMERA_SENSOR_CMD_TYPE_PWR_DOWN:
cmd_length_in_bytes = total_cmd_buf_in_bytes;
rc = cam_sensor_update_power_settings(cmd_buf,
- cmd_length_in_bytes, power_info);
+ cmd_length_in_bytes, power_info,
+ (remain_len -
+ processed_cmd_buf_in_bytes));
processed_cmd_buf_in_bytes +=
cmd_length_in_bytes;
cmd_buf += cmd_length_in_bytes/
sizeof(uint32_t);
if (rc) {
CAM_ERR(CAM_EEPROM, "Failed");
- return rc;
+ goto rel_cmd_buf;
}
break;
case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR:
@@ -616,7 +661,9 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
rc = cam_eeprom_parse_memory_map(
&e_ctrl->cal_data, cmd_buf,
total_cmd_buf_in_bytes,
- &cmd_length_in_bytes, &num_map);
+ &cmd_length_in_bytes, &num_map,
+ (remain_len -
+ processed_cmd_buf_in_bytes));
processed_cmd_buf_in_bytes +=
cmd_length_in_bytes;
cmd_buf += cmd_length_in_bytes/sizeof(uint32_t);
@@ -626,7 +673,18 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
}
}
e_ctrl->cal_data.num_map = num_map + 1;
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_EEPROM, "Failed to put cpu buf: %d",
+ cmd_desc[i].mem_handle);
}
+
+ return rc;
+
+rel_cmd_buf:
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_EEPROM, "Failed to put cpu buf: %d",
+ cmd_desc[i].mem_handle);
+
return rc;
}
@@ -647,6 +705,7 @@ static int32_t cam_eeprom_get_cal_data(struct cam_eeprom_ctrl_t *e_ctrl,
uintptr_t buf_addr;
size_t buf_size;
uint8_t *read_buffer;
+ size_t remain_len = 0;
io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *)
&csl_packet->payload +
@@ -660,6 +719,18 @@ static int32_t cam_eeprom_get_cal_data(struct cam_eeprom_ctrl_t *e_ctrl,
if (io_cfg->direction == CAM_BUF_OUTPUT) {
rc = cam_mem_get_cpu_buf(io_cfg->mem_handle[0],
&buf_addr, &buf_size);
+ if (rc) {
+ CAM_ERR(CAM_EEPROM, "Fail in get buffer: %d",
+ rc);
+ return rc;
+ }
+ if (buf_size <= io_cfg->offsets[0]) {
+ CAM_ERR(CAM_EEPROM, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+
+ remain_len = buf_size - io_cfg->offsets[0];
CAM_DBG(CAM_EEPROM, "buf_addr : %pK, buf_size : %zu\n",
(void *)buf_addr, buf_size);
@@ -667,26 +738,38 @@ static int32_t cam_eeprom_get_cal_data(struct cam_eeprom_ctrl_t *e_ctrl,
if (!read_buffer) {
CAM_ERR(CAM_EEPROM,
"invalid buffer to copy data");
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
read_buffer += io_cfg->offsets[0];
- if (buf_size < e_ctrl->cal_data.num_data) {
+ if (remain_len < e_ctrl->cal_data.num_data) {
CAM_ERR(CAM_EEPROM,
"failed to copy, Invalid size");
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
CAM_DBG(CAM_EEPROM, "copy the data, len:%d",
e_ctrl->cal_data.num_data);
memcpy(read_buffer, e_ctrl->cal_data.mapdata,
e_ctrl->cal_data.num_data);
-
+ if (cam_mem_put_cpu_buf(io_cfg->mem_handle[0]))
+ CAM_WARN(CAM_EEPROM, "Fail in put buffer: 0x%x",
+ io_cfg->mem_handle[0]);
} else {
CAM_ERR(CAM_EEPROM, "Invalid direction");
rc = -EINVAL;
}
}
+
+ return rc;
+
+rel_cmd_buf:
+ if (cam_mem_put_cpu_buf(io_cfg->mem_handle[0]))
+ CAM_WARN(CAM_EEPROM, "Fail in put buffer : %d",
+ io_cfg->mem_handle[0]);
+
return rc;
}
@@ -704,6 +787,7 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
struct cam_config_dev_cmd dev_config;
uintptr_t generic_pkt_addr;
size_t pkt_len;
+ size_t remain_len = 0;
struct cam_packet *csl_packet = NULL;
struct cam_eeprom_soc_private *soc_private =
(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
@@ -723,15 +807,28 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
return rc;
}
- if (dev_config.offset > pkt_len) {
+ remain_len = pkt_len;
+ if ((sizeof(struct cam_packet) > pkt_len) ||
+ ((size_t)dev_config.offset >= pkt_len -
+ sizeof(struct cam_packet))) {
CAM_ERR(CAM_EEPROM,
- "Offset is out of bound: off: %lld, %zu",
- dev_config.offset, pkt_len);
- return -EINVAL;
+ "Inval cam_packet strut size: %zu, len_of_buff: %zu",
+ sizeof(struct cam_packet), pkt_len);
+ rc = -EINVAL;
+ goto release_buf;
}
+ remain_len -= (size_t)dev_config.offset;
csl_packet = (struct cam_packet *)
- (generic_pkt_addr + (uint32_t)dev_config.offset);
+ (generic_pkt_addr + (uint32_t)dev_config.offset);
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_EEPROM, "Invalid packet params");
+ rc = -EINVAL;
+ goto release_buf;
+ }
+
switch (csl_packet->header.op_code & 0xFFFFFF) {
case CAM_EEPROM_PACKET_OPCODE_INIT:
if (e_ctrl->userspace_probe == false) {
@@ -739,7 +836,7 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
e_ctrl->soc_info.dev->of_node, e_ctrl);
if (rc < 0) {
CAM_ERR(CAM_EEPROM, "Failed: rc : %d", rc);
- return rc;
+ goto release_buf;
}
rc = cam_eeprom_get_cal_data(e_ctrl, csl_packet);
vfree(e_ctrl->cal_data.mapdata);
@@ -754,7 +851,7 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
if (rc) {
CAM_ERR(CAM_EEPROM,
"Failed in parsing the pkt");
- return rc;
+ goto release_buf;
}
e_ctrl->cal_data.mapdata =
@@ -797,7 +894,13 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
default:
break;
}
+
+ if (cam_mem_put_cpu_buf(dev_config.packet_handle))
+ CAM_WARN(CAM_EEPROM, "Put cpu buffer failed : %llu",
+ dev_config.packet_handle);
+
return rc;
+
power_down:
cam_eeprom_power_down(e_ctrl);
memdata_free:
@@ -811,6 +914,11 @@ error:
e_ctrl->cal_data.num_data = 0;
e_ctrl->cal_data.num_map = 0;
e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT;
+release_buf:
+ if (cam_mem_put_cpu_buf(dev_config.packet_handle))
+ CAM_WARN(CAM_EEPROM, "Put cpu buffer failed : %llu",
+ dev_config.packet_handle);
+
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c
index 6d8820abb7d7..cf6854c7a527 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -219,7 +219,6 @@ static int cam_eeprom_i2c_driver_probe(struct i2c_client *client,
e_ctrl->bridge_intf.ops.get_dev_info = NULL;
e_ctrl->bridge_intf.ops.link_setup = NULL;
e_ctrl->bridge_intf.ops.apply_req = NULL;
- v4l2_set_subdevdata(&e_ctrl->v4l2_dev_str.sd, e_ctrl);
e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT;
return rc;
@@ -257,13 +256,17 @@ static int cam_eeprom_i2c_driver_remove(struct i2c_client *client)
return -EINVAL;
}
+ CAM_INFO(CAM_EEPROM, "i2c driver remove invoked");
soc_info = &e_ctrl->soc_info;
for (i = 0; i < soc_info->num_clk; i++)
devm_clk_put(soc_info->dev, soc_info->clk[i]);
+ mutex_lock(&(e_ctrl->eeprom_mutex));
+ cam_eeprom_shutdown(e_ctrl);
+ mutex_unlock(&(e_ctrl->eeprom_mutex));
mutex_destroy(&(e_ctrl->eeprom_mutex));
+ cam_unregister_subdev(&(e_ctrl->v4l2_dev_str));
kfree(soc_private);
- kfree(e_ctrl->io_master_info.cci_client);
v4l2_set_subdevdata(&e_ctrl->v4l2_dev_str.sd, NULL);
kfree(e_ctrl);
@@ -388,14 +391,21 @@ static int cam_eeprom_spi_driver_remove(struct spi_device *sdev)
for (i = 0; i < soc_info->num_clk; i++)
devm_clk_put(soc_info->dev, soc_info->clk[i]);
+ mutex_lock(&(e_ctrl->eeprom_mutex));
+ cam_eeprom_shutdown(e_ctrl);
+ mutex_unlock(&(e_ctrl->eeprom_mutex));
+ mutex_destroy(&(e_ctrl->eeprom_mutex));
+ cam_unregister_subdev(&(e_ctrl->v4l2_dev_str));
kfree(e_ctrl->io_master_info.spi_client);
+ e_ctrl->io_master_info.spi_client = NULL;
soc_private =
(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
if (soc_private) {
kfree(soc_private->power_info.gpio_num_info);
+ soc_private->power_info.gpio_num_info = NULL;
kfree(soc_private);
+ soc_private = NULL;
}
- mutex_destroy(&(e_ctrl->eeprom_mutex));
v4l2_set_subdevdata(&e_ctrl->v4l2_dev_str.sd, NULL);
kfree(e_ctrl);
@@ -459,10 +469,7 @@ static int32_t cam_eeprom_platform_driver_probe(
e_ctrl->bridge_intf.ops.get_dev_info = NULL;
e_ctrl->bridge_intf.ops.link_setup = NULL;
e_ctrl->bridge_intf.ops.apply_req = NULL;
-
platform_set_drvdata(pdev, e_ctrl);
- v4l2_set_subdevdata(&e_ctrl->v4l2_dev_str.sd, e_ctrl);
-
e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT;
return rc;
@@ -472,6 +479,7 @@ free_cci_client:
kfree(e_ctrl->io_master_info.cci_client);
free_e_ctrl:
kfree(e_ctrl);
+
return rc;
}
@@ -487,17 +495,23 @@ static int cam_eeprom_platform_driver_remove(struct platform_device *pdev)
return -EINVAL;
}
+ CAM_INFO(CAM_EEPROM, "Platform driver remove invoked");
soc_info = &e_ctrl->soc_info;
for (i = 0; i < soc_info->num_clk; i++)
devm_clk_put(soc_info->dev, soc_info->clk[i]);
+ mutex_lock(&(e_ctrl->eeprom_mutex));
+ cam_eeprom_shutdown(e_ctrl);
+ mutex_unlock(&(e_ctrl->eeprom_mutex));
mutex_destroy(&(e_ctrl->eeprom_mutex));
+ cam_unregister_subdev(&(e_ctrl->v4l2_dev_str));
kfree(soc_info->soc_private);
kfree(e_ctrl->io_master_info.cci_client);
platform_set_drvdata(pdev, NULL);
v4l2_set_subdevdata(&e_ctrl->v4l2_dev_str.sd, NULL);
kfree(e_ctrl);
+
return 0;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c
index 5c9df8ac7abf..4302d4897ea9 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -16,43 +16,78 @@
#include "cam_flash_core.h"
#include "cam_res_mgr_api.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
static int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl,
bool regulator_enable)
{
int rc = 0;
+ struct cam_flash_private_soc *soc_private =
+ (struct cam_flash_private_soc *)
+ flash_ctrl->soc_info.soc_private;
if (!(flash_ctrl->switch_trigger)) {
CAM_ERR(CAM_FLASH, "Invalid argument");
return -EINVAL;
}
- if (regulator_enable &&
- (flash_ctrl->is_regulator_enabled == false)) {
- rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger,
- ENABLE_REGULATOR, NULL);
- if (rc) {
- CAM_ERR(CAM_FLASH, "regulator enable failed rc = %d",
- rc);
- return rc;
- }
- flash_ctrl->is_regulator_enabled = true;
- } else if ((!regulator_enable) &&
- (flash_ctrl->is_regulator_enabled == true)) {
- rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger,
- DISABLE_REGULATOR, NULL);
- if (rc) {
- CAM_ERR(CAM_FLASH, "regulator disable failed rc = %d",
- rc);
- return rc;
+ if (soc_private->is_wled_flash) {
+ if (regulator_enable &&
+ flash_ctrl->is_regulator_enabled == false) {
+ rc = wled_flash_led_prepare(flash_ctrl->switch_trigger,
+ ENABLE_REGULATOR, NULL);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "enable reg failed: rc: %d",
+ rc);
+ return rc;
+ }
+
+ flash_ctrl->is_regulator_enabled = true;
+ } else if (!regulator_enable &&
+ flash_ctrl->is_regulator_enabled == true) {
+ rc = wled_flash_led_prepare(flash_ctrl->switch_trigger,
+ DISABLE_REGULATOR, NULL);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "disalbe reg fail: rc: %d",
+ rc);
+ return rc;
+ }
+
+ flash_ctrl->is_regulator_enabled = false;
+ } else {
+ CAM_ERR(CAM_FLASH, "Wrong Wled flash state: %d",
+ flash_ctrl->flash_state);
+ rc = -EINVAL;
}
- flash_ctrl->is_regulator_enabled = false;
} else {
- CAM_ERR(CAM_FLASH, "Wrong Flash State : %d",
- flash_ctrl->flash_state);
- rc = -EINVAL;
- }
+ if (regulator_enable &&
+ (flash_ctrl->is_regulator_enabled == false)) {
+ rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger,
+ ENABLE_REGULATOR, NULL);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "Regulator enable failed rc = %d", rc);
+ return rc;
+ }
+ flash_ctrl->is_regulator_enabled = true;
+ } else if ((!regulator_enable) &&
+ (flash_ctrl->is_regulator_enabled == true)) {
+ rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger,
+ DISABLE_REGULATOR, NULL);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "Regulator disable failed rc = %d", rc);
+ return rc;
+ }
+
+ flash_ctrl->is_regulator_enabled = false;
+ } else {
+ CAM_ERR(CAM_FLASH, "Wrong Flash State : %d",
+ flash_ctrl->flash_state);
+ rc = -EINVAL;
+ }
+ }
return rc;
}
@@ -171,6 +206,7 @@ int cam_flash_pmic_power_ops(struct cam_flash_ctrl *fctrl,
"Enable Regulator Failed rc = %d", rc);
return rc;
}
+ fctrl->last_flush_req = 0;
}
if (!regulator_enable) {
@@ -267,7 +303,6 @@ int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl,
}
if (type == FLUSH_ALL) {
- cam_flash_off(fctrl);
/* flush all requests*/
for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
fctrl->per_frame[i].cmn_attr.request_id = 0;
@@ -360,7 +395,13 @@ int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush)
}
mutex_lock(&fctrl->flash_mutex);
+ if (fctrl->flash_state == CAM_FLASH_STATE_INIT)
+ goto end;
+
if (flush->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
+ fctrl->last_flush_req = flush->req_id;
+ CAM_DBG(CAM_FLASH, "last reqest to flush is %lld",
+ flush->req_id);
rc = fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0);
if (rc) {
CAM_ERR(CAM_FLASH, "FLUSH_TYPE_ALL failed rc: %d", rc);
@@ -398,37 +439,31 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl,
for (i = 0; i < flash_ctrl->torch_num_sources; i++) {
if (flash_ctrl->torch_trigger[i]) {
max_current = soc_private->torch_max_current[i];
-
if (flash_data->led_current_ma[i] <=
max_current)
curr = flash_data->led_current_ma[i];
else
- curr = soc_private->torch_op_current[i];
-
- CAM_DBG(CAM_PERF,
- "Led_Current[%d] = %d", i, curr);
- cam_res_mgr_led_trigger_event(
- flash_ctrl->torch_trigger[i],
- curr);
+ curr = max_current;
}
+ CAM_DBG(CAM_FLASH, "Led_Torch[%d]: Current: %d",
+ i, curr);
+ cam_res_mgr_led_trigger_event(
+ flash_ctrl->torch_trigger[i], curr);
}
} else if (op == CAMERA_SENSOR_FLASH_OP_FIREHIGH) {
for (i = 0; i < flash_ctrl->flash_num_sources; i++) {
if (flash_ctrl->flash_trigger[i]) {
max_current = soc_private->flash_max_current[i];
-
if (flash_data->led_current_ma[i] <=
max_current)
curr = flash_data->led_current_ma[i];
else
- curr = soc_private->flash_op_current[i];
-
- CAM_DBG(CAM_PERF, "LED flash_current[%d]: %d",
- i, curr);
- cam_res_mgr_led_trigger_event(
- flash_ctrl->flash_trigger[i],
- curr);
+ curr = max_current;
}
+ CAM_DBG(CAM_FLASH, "LED_Flash[%d]: Current: %d",
+ i, curr);
+ cam_res_mgr_led_trigger_event(
+ flash_ctrl->flash_trigger[i], curr);
}
} else {
CAM_ERR(CAM_FLASH, "Wrong Operation: %d", op);
@@ -438,7 +473,7 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl,
if (flash_ctrl->switch_trigger)
cam_res_mgr_led_trigger_event(
flash_ctrl->switch_trigger,
- LED_SWITCH_ON);
+ (enum led_brightness)LED_SWITCH_ON);
return 0;
}
@@ -452,7 +487,7 @@ int cam_flash_off(struct cam_flash_ctrl *flash_ctrl)
if (flash_ctrl->switch_trigger)
cam_res_mgr_led_trigger_event(flash_ctrl->switch_trigger,
- LED_SWITCH_OFF);
+ (enum led_brightness)LED_SWITCH_OFF);
flash_ctrl->flash_state = CAM_FLASH_STATE_START;
return 0;
@@ -591,11 +626,15 @@ static int cam_flash_pmic_delete_req(struct cam_flash_ctrl *fctrl,
}
static int32_t cam_flash_slaveInfo_pkt_parser(struct cam_flash_ctrl *fctrl,
- uint32_t *cmd_buf)
+ uint32_t *cmd_buf, size_t len)
{
int32_t rc = 0;
struct cam_cmd_i2c_info *i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
+ if (len < sizeof(struct cam_cmd_i2c_info)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ return -EINVAL;
+ }
if (fctrl->io_master_info.master_type == CCI_MASTER) {
fctrl->io_master_info.cci_client->cci_i2c_master =
fctrl->cci_i2c_master;
@@ -870,6 +909,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
uint32_t *offset = NULL;
uint32_t frm_offset = 0;
size_t len_of_buffer;
+ size_t remain_len;
struct cam_flash_init *flash_init = NULL;
struct common_header *cmn_hdr = NULL;
struct cam_control *ioctl_ctrl = NULL;
@@ -897,19 +937,42 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
rc = cam_mem_get_cpu_buf(config.packet_handle,
&generic_ptr, &len_of_buffer);
if (rc) {
- CAM_ERR(CAM_FLASH, "Failed in getting the buffer : %d", rc);
+ CAM_ERR(CAM_FLASH, "Failed in getting the packet : %d", rc);
return rc;
}
-
- if (config.offset > len_of_buffer) {
+ remain_len = len_of_buffer;
+ if ((sizeof(struct cam_packet) > len_of_buffer) ||
+ ((size_t)config.offset >= len_of_buffer -
+ sizeof(struct cam_packet))) {
CAM_ERR(CAM_FLASH,
- "offset is out of bounds: offset: %lld len: %zu",
- config.offset, len_of_buffer);
+ "Inval cam_packet strut size: %zu, len_of_buff: %zu",
+ sizeof(struct cam_packet), len_of_buffer);
return -EINVAL;
}
+ remain_len -= (size_t)config.offset;
/* Add offset to the flash csl header */
csl_packet = (struct cam_packet *)(generic_ptr + config.offset);
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_FLASH, "Invalid packet params");
+ return -EINVAL;
+ }
+
+ if ((csl_packet->header.op_code & 0xFFFFFF) !=
+ CAM_FLASH_PACKET_OPCODE_INIT &&
+ csl_packet->header.request_id <= fctrl->last_flush_req
+ && fctrl->last_flush_req != 0) {
+ CAM_DBG(CAM_FLASH,
+ "reject request %lld, last request to flush %lld",
+ csl_packet->header.request_id, fctrl->last_flush_req);
+ return -EINVAL;
+ }
+
+ if (csl_packet->header.request_id > fctrl->last_flush_req)
+ fctrl->last_flush_req = 0;
+
switch (csl_packet->header.op_code & 0xFFFFFF) {
case CAM_FLASH_PACKET_OPCODE_INIT: {
/* INIT packet*/
@@ -934,6 +997,15 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
CAM_ERR(CAM_FLASH, "invalid cmd buf");
return -EINVAL;
}
+
+ if ((len_of_buffer < sizeof(struct common_header)) ||
+ (cmd_desc[i].offset >
+ (len_of_buffer -
+ sizeof(struct common_header)))) {
+ CAM_ERR(CAM_FLASH, "invalid cmd buf length");
+ return -EINVAL;
+ }
+ remain_len = len_of_buffer - cmd_desc[i].offset;
cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
cmn_hdr = (struct common_header *)cmd_buf;
@@ -944,6 +1016,12 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
total_cmd_buf_in_bytes);
switch (cmn_hdr->cmd_type) {
case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO:
+ if (len_of_buffer <
+ sizeof(struct cam_flash_init)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ return -EINVAL;
+ }
+
flash_init = (struct cam_flash_init *)cmd_buf;
fctrl->flash_type = flash_init->flash_type;
cmd_length_in_bytes =
@@ -955,7 +1033,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
break;
case CAMERA_SENSOR_CMD_TYPE_I2C_INFO:
rc = cam_flash_slaveInfo_pkt_parser(
- fctrl, cmd_buf);
+ fctrl, cmd_buf, remain_len);
if (rc < 0) {
CAM_ERR(CAM_FLASH,
"Failed parsing slave info: rc: %d",
@@ -978,7 +1056,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
rc = cam_sensor_update_power_settings(
cmd_buf,
total_cmd_buf_in_bytes,
- &fctrl->power_info);
+ &fctrl->power_info, remain_len);
processed_cmd_buf_in_bytes +=
cmd_length_in_bytes;
cmd_buf += cmd_length_in_bytes/
@@ -1171,11 +1249,12 @@ update_req_mgr:
int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
{
int rc = 0, i = 0;
- uintptr_t generic_ptr;
+ uintptr_t generic_ptr, cmd_buf_ptr;
uint32_t *cmd_buf = NULL;
uint32_t *offset = NULL;
uint32_t frm_offset = 0;
size_t len_of_buffer;
+ size_t remain_len;
struct cam_control *ioctl_ctrl = NULL;
struct cam_packet *csl_packet = NULL;
struct cam_cmd_buf_desc *cmd_desc = NULL;
@@ -1187,11 +1266,16 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
struct cam_flash_set_on_off *flash_operation_info = NULL;
struct cam_flash_query_curr *flash_query_info = NULL;
struct cam_flash_frame_setting *flash_data = NULL;
+ struct cam_flash_private_soc *soc_private = NULL;
if (!fctrl || !arg) {
CAM_ERR(CAM_FLASH, "fctrl/arg is NULL");
return -EINVAL;
}
+
+ soc_private = (struct cam_flash_private_soc *)
+ fctrl->soc_info.soc_private;
+
/* getting CSL Packet */
ioctl_ctrl = (struct cam_control *)arg;
@@ -1206,20 +1290,45 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
rc = cam_mem_get_cpu_buf(config.packet_handle,
&generic_ptr, &len_of_buffer);
if (rc) {
- CAM_ERR(CAM_FLASH, "Failed in getting the buffer : %d", rc);
+ CAM_ERR(CAM_FLASH, "Failed in getting the packet: %d", rc);
return rc;
}
- if (config.offset > len_of_buffer) {
+ remain_len = len_of_buffer;
+ if ((sizeof(struct cam_packet) > len_of_buffer) ||
+ ((size_t)config.offset >= len_of_buffer -
+ sizeof(struct cam_packet))) {
CAM_ERR(CAM_FLASH,
- "offset is out of bounds: offset: %lld len: %zu",
- config.offset, len_of_buffer);
- return -EINVAL;
+ "Inval cam_packet strut size: %zu, len_of_buff: %zu",
+ sizeof(struct cam_packet), len_of_buffer);
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
+ remain_len -= (size_t)config.offset;
/* Add offset to the flash csl header */
- csl_packet =
- (struct cam_packet *)(generic_ptr + (uint32_t)config.offset);
+ csl_packet = (struct cam_packet *)(generic_ptr + config.offset);
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_FLASH, "Invalid packet params");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+
+ if ((csl_packet->header.op_code & 0xFFFFFF) !=
+ CAM_FLASH_PACKET_OPCODE_INIT &&
+ csl_packet->header.request_id <= fctrl->last_flush_req
+ && fctrl->last_flush_req != 0) {
+ CAM_WARN(CAM_FLASH,
+ "reject request %lld, last request to flush %u",
+ csl_packet->header.request_id, fctrl->last_flush_req);
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+
+ if (csl_packet->header.request_id > fctrl->last_flush_req)
+ fctrl->last_flush_req = 0;
switch (csl_packet->header.op_code & 0xFFFFFF) {
case CAM_FLASH_PACKET_OPCODE_INIT: {
@@ -1228,8 +1337,20 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
csl_packet->cmd_buf_offset);
cmd_desc = (struct cam_cmd_buf_desc *)(offset);
rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
- &generic_ptr, &len_of_buffer);
- cmd_buf = (uint32_t *)((uint8_t *)generic_ptr +
+ &cmd_buf_ptr, &len_of_buffer);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "Fail in get buffer: %d", rc);
+ goto rel_pkt_buf;
+ }
+ if ((len_of_buffer < sizeof(struct cam_flash_init)) ||
+ (cmd_desc->offset >
+ (len_of_buffer - sizeof(struct cam_flash_init)))) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+ remain_len = len_of_buffer - cmd_desc->offset;
+ cmd_buf = (uint32_t *)((uint8_t *)cmd_buf_ptr +
cmd_desc->offset);
cam_flash_info = (struct cam_flash_init *)cmd_buf;
@@ -1248,7 +1369,7 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
if (rc) {
CAM_ERR(CAM_FLASH,
"Enable Regulator Failed rc = %d", rc);
- return rc;
+ goto rel_cmd_buf;
}
fctrl->flash_state =
@@ -1258,8 +1379,26 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE: {
CAM_DBG(CAM_FLASH, "INIT_FIRE Operation");
+ if (remain_len < sizeof(struct cam_flash_set_on_off)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+
flash_operation_info =
(struct cam_flash_set_on_off *) cmd_buf;
+ if (!flash_operation_info) {
+ CAM_ERR(CAM_FLASH,
+ "flash_operation_info Null");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+ if (flash_operation_info->count >
+ CAM_FLASH_MAX_LED_TRIGGERS) {
+ CAM_ERR(CAM_FLASH, "led count out of limit");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
fctrl->nrt_info.cmn_attr.count =
flash_operation_info->count;
fctrl->nrt_info.cmn_attr.request_id = 0;
@@ -1284,8 +1423,13 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
default:
CAM_ERR(CAM_FLASH, "Wrong cmd_type = %d",
cam_flash_info->cmd_type);
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
+
+ if (cam_mem_put_cpu_buf(cmd_desc->mem_handle))
+ CAM_WARN(CAM_FLASH, "Fail in put buffer: %d",
+ cmd_desc->mem_handle);
break;
}
case CAM_FLASH_PACKET_OPCODE_SET_OPS: {
@@ -1306,13 +1450,28 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
flash_data->cmn_attr.is_settings_valid = true;
cmd_desc = (struct cam_cmd_buf_desc *)(offset);
rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
- &generic_ptr, &len_of_buffer);
- cmd_buf = (uint32_t *)((uint8_t *)generic_ptr +
- cmd_desc->offset);
+ &cmd_buf_ptr, &len_of_buffer);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "Fail in get buffer: 0x%x",
+ cmd_desc->mem_handle);
+ goto rel_pkt_buf;
+ }
- if (!cmd_buf)
- return -EINVAL;
+ if ((len_of_buffer < sizeof(struct common_header)) ||
+ (cmd_desc->offset >
+ (len_of_buffer - sizeof(struct common_header)))) {
+ CAM_ERR(CAM_FLASH, "not enough buffer");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+ remain_len = len_of_buffer - cmd_desc->offset;
+ cmd_buf = (uint32_t *)((uint8_t *)cmd_buf_ptr +
+ cmd_desc->offset);
+ if (!cmd_buf) {
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
cmn_hdr = (struct common_header *)cmd_buf;
switch (cmn_hdr->cmd_type) {
@@ -1325,7 +1484,12 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
CAM_WARN(CAM_FLASH,
"Rxed Flash fire ops without linking");
flash_data->cmn_attr.is_settings_valid = false;
- return 0;
+ goto rel_cmd_buf;
+ }
+ if (remain_len < sizeof(struct cam_flash_set_on_off)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
flash_operation_info =
@@ -1333,7 +1497,14 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
if (!flash_operation_info) {
CAM_ERR(CAM_FLASH,
"flash_operation_info Null");
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+ if (flash_operation_info->count >
+ CAM_FLASH_MAX_LED_TRIGGERS) {
+ CAM_ERR(CAM_FLASH, "led count out of limit");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
flash_data->opcode = flash_operation_info->opcode;
@@ -1350,8 +1521,12 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
default:
CAM_ERR(CAM_FLASH, "Wrong cmd_type = %d",
cmn_hdr->cmd_type);
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
+ if (cam_mem_put_cpu_buf(cmd_desc->mem_handle))
+ CAM_WARN(CAM_FLASH, "Fail in put buffer: 0x%x",
+ cmd_desc->mem_handle);
break;
}
case CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS: {
@@ -1360,16 +1535,47 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
fctrl->nrt_info.cmn_attr.is_settings_valid = true;
cmd_desc = (struct cam_cmd_buf_desc *)(offset);
rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
- &generic_ptr, &len_of_buffer);
- cmd_buf = (uint32_t *)((uint8_t *)generic_ptr +
+ &cmd_buf_ptr, &len_of_buffer);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "Fail in get buffer: %d", rc);
+ goto rel_pkt_buf;
+ }
+
+ if ((len_of_buffer < sizeof(struct common_header)) ||
+ (cmd_desc->offset >
+ (len_of_buffer - sizeof(struct common_header)))) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+ remain_len = len_of_buffer - cmd_desc->offset;
+ cmd_buf = (uint32_t *)((uint8_t *)cmd_buf_ptr +
cmd_desc->offset);
cmn_hdr = (struct common_header *)cmd_buf;
switch (cmn_hdr->cmd_type) {
case CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET: {
CAM_DBG(CAM_FLASH, "Widget Flash Operation");
+ if (remain_len < sizeof(struct cam_flash_set_on_off)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
flash_operation_info =
(struct cam_flash_set_on_off *) cmd_buf;
+ if (!flash_operation_info) {
+ CAM_ERR(CAM_FLASH,
+ "flash_operation_info Null");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+ if (flash_operation_info->count >
+ CAM_FLASH_MAX_LED_TRIGGERS) {
+ CAM_ERR(CAM_FLASH, "led count out of limit");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+
fctrl->nrt_info.cmn_attr.count =
flash_operation_info->count;
fctrl->nrt_info.cmn_attr.request_id = 0;
@@ -1386,29 +1592,61 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
if (rc)
CAM_ERR(CAM_FLASH, "Apply setting failed: %d",
rc);
- return rc;
+ goto rel_cmd_buf;
}
case CAMERA_SENSOR_FLASH_CMD_TYPE_QUERYCURR: {
int query_curr_ma = 0;
+ if (remain_len < sizeof(struct cam_flash_query_curr)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
flash_query_info =
(struct cam_flash_query_curr *)cmd_buf;
- rc = qpnp_flash_led_prepare(fctrl->switch_trigger,
- QUERY_MAX_CURRENT, &query_curr_ma);
+ if (soc_private->is_wled_flash)
+ rc = wled_flash_led_prepare(
+ fctrl->switch_trigger,
+ QUERY_MAX_AVAIL_CURRENT,
+ &query_curr_ma);
+ else
+ rc = qpnp_flash_led_prepare(
+ fctrl->switch_trigger,
+ QUERY_MAX_AVAIL_CURRENT,
+ &query_curr_ma);
+
CAM_DBG(CAM_FLASH, "query_curr_ma = %d",
query_curr_ma);
if (rc) {
CAM_ERR(CAM_FLASH,
"Query current failed with rc=%d", rc);
- return rc;
+ goto rel_cmd_buf;
}
flash_query_info->query_current_ma = query_curr_ma;
break;
}
case CAMERA_SENSOR_FLASH_CMD_TYPE_RER: {
rc = 0;
+ if (remain_len < sizeof(struct cam_flash_set_rer)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
flash_rer_info = (struct cam_flash_set_rer *)cmd_buf;
+ if (!flash_rer_info) {
+ CAM_ERR(CAM_FLASH,
+ "flash_rer_info Null");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+ if (flash_rer_info->count >
+ CAM_FLASH_MAX_LED_TRIGGERS) {
+ CAM_ERR(CAM_FLASH, "led count out of limit");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+
fctrl->nrt_info.cmn_attr.cmd_type =
CAMERA_SENSOR_FLASH_CMD_TYPE_RER;
fctrl->nrt_info.opcode = flash_rer_info->opcode;
@@ -1425,18 +1663,21 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
fctrl->nrt_info.led_current_ma[i] =
flash_rer_info->led_current_ma[i];
-
rc = fctrl->func_tbl.apply_setting(fctrl, 0);
if (rc)
CAM_ERR(CAM_FLASH, "apply_setting failed: %d",
rc);
- return rc;
+ goto rel_cmd_buf;
}
default:
CAM_ERR(CAM_FLASH, "Wrong cmd_type : %d",
cmn_hdr->cmd_type);
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
+ if (cam_mem_put_cpu_buf(cmd_desc->mem_handle))
+ CAM_WARN(CAM_FLASH, "Fail in put buffer: 0x%x",
+ cmd_desc->mem_handle);
break;
}
case CAM_PKT_NOP_OPCODE: {
@@ -1448,7 +1689,7 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
"Rxed NOP packets without linking");
fctrl->per_frame[frm_offset].cmn_attr.is_settings_valid
= false;
- return 0;
+ goto rel_pkt_buf;
}
fctrl->per_frame[frm_offset].cmn_attr.is_settings_valid = false;
@@ -1456,14 +1697,15 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
fctrl->per_frame[frm_offset].opcode = CAM_PKT_NOP_OPCODE;
CAM_DBG(CAM_FLASH, "NOP Packet is Received: req_id: %llu",
csl_packet->header.request_id);
- goto update_req_mgr;
+ break;
}
default:
CAM_ERR(CAM_FLASH, "Wrong Opcode : %d",
(csl_packet->header.op_code & 0xFFFFFF));
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
-update_req_mgr:
+
if (((csl_packet->header.op_code & 0xFFFFF) ==
CAM_PKT_NOP_OPCODE) ||
((csl_packet->header.op_code & 0xFFFFF) ==
@@ -1484,6 +1726,21 @@ update_req_mgr:
CAM_DBG(CAM_FLASH, "add req to req_mgr= %lld", add_req.req_id);
}
+ if (cam_mem_put_cpu_buf(config.packet_handle))
+ CAM_WARN(CAM_FLASH, "Failed in put the buffer: %llu ",
+ config.packet_handle);
+
+ return 0;
+
+rel_cmd_buf:
+ if (cam_mem_put_cpu_buf(cmd_desc->mem_handle))
+ CAM_WARN(CAM_FLASH, "Fail in put buffer: %d",
+ cmd_desc->mem_handle);
+rel_pkt_buf:
+ if (cam_mem_put_cpu_buf(config.packet_handle))
+ CAM_WARN(CAM_FLASH, "Failed in put the buffer: %llu ",
+ config.packet_handle);
+
return rc;
}
@@ -1534,6 +1791,7 @@ int cam_flash_release_dev(struct cam_flash_ctrl *fctrl)
fctrl->bridge_intf.device_hdl = -1;
fctrl->bridge_intf.link_hdl = -1;
fctrl->bridge_intf.session_hdl = -1;
+ fctrl->last_flush_req = 0;
}
return rc;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.h
index 1bd3b31c1668..875d13c51ee0 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,15 +13,20 @@
#ifndef _CAM_FLASH_CORE_H_
#define _CAM_FLASH_CORE_H_
-#include <linux/leds-qpnp-flash.h>
#include <media/cam_sensor.h>
#include "cam_flash_dev.h"
+#define QUERY_MAX_AVAIL_CURRENT BIT(2)
+
int cam_flash_publish_dev_info(struct cam_req_mgr_device_info *info);
int cam_flash_establish_link(struct cam_req_mgr_core_dev_link_setup *link);
int cam_flash_apply_request(struct cam_req_mgr_apply_request *apply);
int cam_flash_process_evt(struct cam_req_mgr_link_evt_data *event_data);
int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush);
-
+static inline int wled_flash_led_prepare(struct led_trigger *trig, int options,
+ int *max_current)
+{
+ return -EINVAL;
+}
#endif /*_CAM_FLASH_CORE_H_*/
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c
index f5177d6796b5..948fc9a9c990 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -181,7 +181,9 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
goto release_mutex;
}
+ cam_flash_off(fctrl);
fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0);
+ fctrl->last_flush_req = 0;
fctrl->flash_state = CAM_FLASH_STATE_ACQUIRE;
break;
}
@@ -318,7 +320,14 @@ static int cam_flash_platform_remove(struct platform_device *pdev)
return 0;
}
- devm_kfree(&pdev->dev, fctrl);
+ CAM_INFO(CAM_FLASH, "Platform remove invoked");
+ mutex_lock(&fctrl->flash_mutex);
+ cam_flash_shutdown(fctrl);
+ mutex_unlock(&fctrl->flash_mutex);
+ cam_unregister_subdev(&(fctrl->v4l2_dev_str));
+ platform_set_drvdata(pdev, NULL);
+ v4l2_set_subdevdata(&fctrl->v4l2_dev_str.sd, NULL);
+ kfree(fctrl);
return 0;
}
@@ -332,6 +341,8 @@ static int32_t cam_flash_i2c_driver_remove(struct i2c_client *client)
CAM_ERR(CAM_FLASH, "Flash device is NULL");
return -EINVAL;
}
+
+ CAM_INFO(CAM_FLASH, "i2c driver remove invoked");
/*Free Allocated Mem */
kfree(fctrl->i2c_data.per_frame);
fctrl->i2c_data.per_frame = NULL;
@@ -483,6 +494,7 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev)
fctrl->bridge_intf.ops.link_setup = cam_flash_establish_link;
fctrl->bridge_intf.ops.apply_req = cam_flash_apply_request;
fctrl->bridge_intf.ops.flush_req = cam_flash_flush_request;
+ fctrl->last_flush_req = 0;
mutex_init(&(fctrl->flash_mutex));
@@ -569,6 +581,7 @@ static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client,
fctrl->bridge_intf.ops.link_setup = cam_flash_establish_link;
fctrl->bridge_intf.ops.apply_req = cam_flash_apply_request;
fctrl->bridge_intf.ops.flush_req = cam_flash_flush_request;
+ fctrl->last_flush_req = 0;
mutex_init(&(fctrl->flash_mutex));
fctrl->flash_state = CAM_FLASH_STATE_INIT;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.h
index 8e5deef871e5..ea5ea3c9997b 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -21,6 +21,7 @@
#include <linux/of.h>
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/leds-qpnp-flash.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-event.h>
@@ -135,6 +136,7 @@ struct cam_flash_frame_setting {
* @torch_trigger_name : Torch trigger name array
* @torch_op_current : Torch operational current
* @torch_max_current : Max supported current for LED in torch mode
+ * @is_wled_flash : Detection between WLED/LED flash
*/
struct cam_flash_private_soc {
@@ -146,6 +148,7 @@ struct cam_flash_private_soc {
const char *torch_trigger_name[CAM_FLASH_MAX_LED_TRIGGERS];
uint32_t torch_op_current[CAM_FLASH_MAX_LED_TRIGGERS];
uint32_t torch_max_current[CAM_FLASH_MAX_LED_TRIGGERS];
+ bool is_wled_flash;
};
struct cam_flash_func_tbl {
@@ -180,6 +183,7 @@ struct cam_flash_func_tbl {
* @cci_i2c_master : I2C structure
* @io_master_info : Information about the communication master
* @i2c_data : I2C register settings
+ * @last_flush_req : last request to flush
*/
struct cam_flash_ctrl {
struct cam_hw_soc_info soc_info;
@@ -205,6 +209,7 @@ struct cam_flash_ctrl {
enum cci_i2c_master_t cci_i2c_master;
struct camera_io_master io_master_info;
struct i2c_data_settings i2c_data;
+ uint32_t last_flush_req;
};
int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg);
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_soc.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_soc.c
index 22a124d86f93..9195c8143d3c 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_soc.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -26,9 +26,12 @@ static int32_t cam_get_source_node_info(
struct device_node *torch_src_node = NULL;
struct device_node *switch_src_node = NULL;
+ soc_private->is_wled_flash =
+ of_property_read_bool(of_node, "wled-flash-support");
+
switch_src_node = of_parse_phandle(of_node, "switch-source", 0);
if (!switch_src_node) {
- CAM_DBG(CAM_FLASH, "switch_src_node NULL");
+ CAM_WARN(CAM_FLASH, "switch_src_node NULL");
} else {
rc = of_property_read_string(switch_src_node,
"qcom,default-led-trigger",
@@ -75,46 +78,61 @@ static int32_t cam_get_source_node_info(
continue;
}
- CAM_DBG(CAM_FLASH, "default trigger %s",
+ CAM_DBG(CAM_FLASH, "Flash default trigger %s",
soc_private->flash_trigger_name[i]);
+ cam_res_mgr_led_trigger_register(
+ soc_private->flash_trigger_name[i],
+ &fctrl->flash_trigger[i]);
+
+ if (soc_private->is_wled_flash) {
+ rc = wled_flash_led_prepare(
+ fctrl->flash_trigger[i],
+ QUERY_MAX_CURRENT,
+ &soc_private->flash_max_current[i]);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "WLED FLASH max_current read fail: %d",
+ rc);
+ of_node_put(flash_src_node);
+ rc = 0;
+ continue;
+ }
+ } else {
+ rc = of_property_read_u32(flash_src_node,
+ "qcom,max-current",
+ &soc_private->flash_max_current[i]);
+ if (rc < 0) {
+ CAM_WARN(CAM_FLASH,
+ "LED FLASH max-current read fail: %d",
+ rc);
+ of_node_put(flash_src_node);
+ continue;
+ }
+ }
/* Read operational-current */
rc = of_property_read_u32(flash_src_node,
"qcom,current-ma",
&soc_private->flash_op_current[i]);
if (rc) {
- CAM_WARN(CAM_FLASH, "op-current: read failed");
- of_node_put(flash_src_node);
- continue;
- }
-
- /* Read max-current */
- rc = of_property_read_u32(flash_src_node,
- "qcom,max-current",
- &soc_private->flash_max_current[i]);
- if (rc) {
- CAM_WARN(CAM_FLASH,
- "max-current: read failed");
- of_node_put(flash_src_node);
- continue;
+ CAM_INFO(CAM_FLASH, "op-current: read failed");
+ rc = 0;
}
/* Read max-duration */
rc = of_property_read_u32(flash_src_node,
"qcom,duration-ms",
&soc_private->flash_max_duration[i]);
- if (rc)
- CAM_WARN(CAM_FLASH,
- "max-duration: read failed");
-
+ if (rc) {
+ CAM_INFO(CAM_FLASH,
+ "max-duration prop unavailable: %d",
+ rc);
+ rc = 0;
+ }
of_node_put(flash_src_node);
- CAM_DBG(CAM_FLASH, "max_current[%d]: %d",
+ CAM_DBG(CAM_FLASH, "MainFlashMaxCurrent[%d]: %d",
i, soc_private->flash_max_current[i]);
-
- cam_res_mgr_led_trigger_register(
- soc_private->flash_trigger_name[i],
- &fctrl->flash_trigger[i]);
}
}
@@ -147,35 +165,51 @@ static int32_t cam_get_source_node_info(
continue;
}
+ CAM_DBG(CAM_FLASH, "Torch default trigger %s",
+ soc_private->torch_trigger_name[i]);
+ cam_res_mgr_led_trigger_register(
+ soc_private->torch_trigger_name[i],
+ &fctrl->torch_trigger[i]);
+
+ if (soc_private->is_wled_flash) {
+ rc = wled_flash_led_prepare(
+ fctrl->torch_trigger[i],
+ QUERY_MAX_CURRENT,
+ &soc_private->torch_max_current[i]);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "WLED TORCH max_current read fail: %d",
+ rc);
+ of_node_put(torch_src_node);
+ continue;
+ }
+ } else {
+ rc = of_property_read_u32(torch_src_node,
+ "qcom,max-current",
+ &soc_private->torch_max_current[i]);
+ if (rc < 0) {
+ CAM_WARN(CAM_FLASH,
+ "LED-TORCH max-current read failed: %d",
+ rc);
+ of_node_put(torch_src_node);
+ continue;
+ }
+ }
+
/* Read operational-current */
rc = of_property_read_u32(torch_src_node,
"qcom,current-ma",
&soc_private->torch_op_current[i]);
if (rc < 0) {
- CAM_WARN(CAM_FLASH, "current: read failed");
- of_node_put(torch_src_node);
- continue;
- }
-
- /* Read max-current */
- rc = of_property_read_u32(torch_src_node,
- "qcom,max-current",
- &soc_private->torch_max_current[i]);
- if (rc < 0) {
CAM_WARN(CAM_FLASH,
- "max-current: read failed");
- of_node_put(torch_src_node);
- continue;
+ "op-current prop unavailable: %d", rc);
+ rc = 0;
}
of_node_put(torch_src_node);
- CAM_DBG(CAM_FLASH, "max_current[%d]: %d",
+ CAM_DBG(CAM_FLASH, "TorchMaxCurrent[%d]: %d",
i, soc_private->torch_max_current[i]);
-
- cam_res_mgr_led_trigger_register(
- soc_private->torch_trigger_name[i],
- &fctrl->torch_trigger[i]);
}
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c
index b8ebc15e7fd5..a5c7039cc2da 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -19,6 +19,7 @@
#include "cam_debug_util.h"
#include "cam_res_mgr_api.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
int32_t cam_ois_construct_default_power_setting(
struct cam_sensor_power_ctrl_t *power_info)
@@ -256,12 +257,12 @@ static int cam_ois_apply_settings(struct cam_ois_ctrl_t *o_ctrl,
}
static int cam_ois_slaveInfo_pkt_parser(struct cam_ois_ctrl_t *o_ctrl,
- uint32_t *cmd_buf)
+ uint32_t *cmd_buf, size_t len)
{
int32_t rc = 0;
struct cam_cmd_ois_info *ois_info;
- if (!o_ctrl || !cmd_buf) {
+ if (!o_ctrl || !cmd_buf || len < sizeof(struct cam_cmd_ois_info)) {
CAM_ERR(CAM_OIS, "Invalid Args");
return -EINVAL;
}
@@ -274,7 +275,8 @@ static int cam_ois_slaveInfo_pkt_parser(struct cam_ois_ctrl_t *o_ctrl,
ois_info->slave_addr >> 1;
o_ctrl->ois_fw_flag = ois_info->ois_fw_flag;
o_ctrl->is_ois_calib = ois_info->is_ois_calib;
- memcpy(o_ctrl->ois_name, ois_info->ois_name, 32);
+ memcpy(o_ctrl->ois_name, ois_info->ois_name, OIS_NAME_LEN);
+ o_ctrl->ois_name[OIS_NAME_LEN - 1] = '\0';
o_ctrl->io_master_info.cci_client->retries = 3;
o_ctrl->io_master_info.cci_client->id_map = 0;
memcpy(&(o_ctrl->opcode), &(ois_info->opcode),
@@ -433,6 +435,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
struct cam_cmd_buf_desc *cmd_desc = NULL;
uintptr_t generic_pkt_addr;
size_t pkt_len;
+ size_t remain_len = 0;
struct cam_packet *csl_packet = NULL;
size_t len_of_buff = 0;
uint32_t *offset = NULL, *cmd_buf;
@@ -453,15 +456,29 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
return rc;
}
- if (dev_config.offset > pkt_len) {
+ remain_len = pkt_len;
+ if ((sizeof(struct cam_packet) > pkt_len) ||
+ ((size_t)dev_config.offset >= pkt_len -
+ sizeof(struct cam_packet))) {
CAM_ERR(CAM_OIS,
- "offset is out of bound: off: %lld len: %zu",
- dev_config.offset, pkt_len);
- return -EINVAL;
+ "Inval cam_packet strut size: %zu, len_of_buff: %zu",
+ sizeof(struct cam_packet), pkt_len);
+ rc = -EINVAL;
+ goto rel_pkt;
}
+ remain_len -= (size_t)dev_config.offset;
csl_packet = (struct cam_packet *)
(generic_pkt_addr + (uint32_t)dev_config.offset);
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_OIS, "Invalid packet params");
+ rc = -EINVAL;
+ goto rel_pkt;
+ }
+
+
switch (csl_packet->header.op_code & 0xFFFFFF) {
case CAM_OIS_PACKET_OPCODE_INIT:
offset = (uint32_t *)&csl_packet->payload;
@@ -477,25 +494,37 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
&generic_ptr, &len_of_buff);
if (rc < 0) {
- CAM_ERR(CAM_OIS, "Failed to get cpu buf");
- return rc;
+ CAM_ERR(CAM_OIS, "Failed to get cpu buf : 0x%x",
+ cmd_desc[i].mem_handle);
+ goto rel_pkt;
}
cmd_buf = (uint32_t *)generic_ptr;
if (!cmd_buf) {
CAM_ERR(CAM_OIS, "invalid cmd buf");
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+
+ if ((len_of_buff < sizeof(struct common_header)) ||
+ (cmd_desc[i].offset > (len_of_buff -
+ sizeof(struct common_header)))) {
+ CAM_ERR(CAM_OIS,
+ "Invalid length for sensor cmd");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
+ remain_len = len_of_buff - cmd_desc[i].offset;
cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
cmm_hdr = (struct common_header *)cmd_buf;
switch (cmm_hdr->cmd_type) {
case CAMERA_SENSOR_CMD_TYPE_I2C_INFO:
rc = cam_ois_slaveInfo_pkt_parser(
- o_ctrl, cmd_buf);
+ o_ctrl, cmd_buf, remain_len);
if (rc < 0) {
CAM_ERR(CAM_OIS,
"Failed in parsing slave info");
- return rc;
+ goto rel_cmd_buf;
}
break;
case CAMERA_SENSOR_CMD_TYPE_PWR_UP:
@@ -505,11 +534,11 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
rc = cam_sensor_update_power_settings(
cmd_buf,
total_cmd_buf_in_bytes,
- power_info);
+ power_info, remain_len);
if (rc) {
CAM_ERR(CAM_OIS,
"Failed: parse power settings");
- return rc;
+ goto rel_cmd_buf;
}
break;
default:
@@ -527,7 +556,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
if (rc < 0) {
CAM_ERR(CAM_OIS,
"init parsing failed: %d", rc);
- return rc;
+ goto rel_cmd_buf;
}
} else if ((o_ctrl->is_ois_calib != 0) &&
(o_ctrl->i2c_calib_data.is_settings_valid ==
@@ -544,18 +573,21 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
if (rc < 0) {
CAM_ERR(CAM_OIS,
"Calib parsing failed: %d", rc);
- return rc;
+ goto rel_cmd_buf;
}
}
break;
}
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_OIS, "Failed to put cpu buf: %d",
+ cmd_desc[i].mem_handle);
}
if (o_ctrl->cam_ois_state != CAM_OIS_CONFIG) {
rc = cam_ois_power_up(o_ctrl);
if (rc) {
CAM_ERR(CAM_OIS, " OIS Power up failed");
- return rc;
+ goto rel_pkt;
}
o_ctrl->cam_ois_state = CAM_OIS_CONFIG;
}
@@ -602,7 +634,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
CAM_WARN(CAM_OIS,
"Not in right state to control OIS: %d",
o_ctrl->cam_ois_state);
- return rc;
+ goto rel_pkt;
}
offset = (uint32_t *)&csl_packet->payload;
offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t));
@@ -615,26 +647,43 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
cmd_desc, 1);
if (rc < 0) {
CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc);
- return rc;
+ goto rel_pkt;
}
rc = cam_ois_apply_settings(o_ctrl, i2c_reg_settings);
if (rc < 0) {
CAM_ERR(CAM_OIS, "Cannot apply mode settings");
- return rc;
+ goto rel_pkt;
}
rc = delete_request(i2c_reg_settings);
- if (rc < 0)
+ if (rc < 0) {
CAM_ERR(CAM_OIS,
"Fail deleting Mode data: rc: %d", rc);
+ goto rel_pkt;
+ }
break;
default:
- break;
+ CAM_ERR(CAM_OIS, "Invalid Opcode: %d",
+ (csl_packet->header.op_code & 0xFFFFFF));
+ rc = -EINVAL;
+ goto rel_pkt;
}
- return rc;
+
+ if (!rc)
+ goto rel_pkt;
+
+rel_cmd_buf:
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_OIS, "Failed to put cpu buf: %d",
+ cmd_desc[i].mem_handle);
pwr_dwn:
cam_ois_power_down(o_ctrl);
+rel_pkt:
+ if (cam_mem_put_cpu_buf(dev_config.packet_handle))
+ CAM_WARN(CAM_OIS, "Fail in put buffer: %llu",
+ dev_config.packet_handle);
+
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.h
index d6f0ec564508..06022ababf4e 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -16,6 +16,8 @@
#include <linux/dma-contiguous.h>
#include "cam_ois_dev.h"
+#define OIS_NAME_LEN 32
+
/**
* @power_info: power setting info to control the power
*
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_dev.c
index 5d16a4e54d04..db583340dad4 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -229,20 +229,23 @@ static int cam_ois_i2c_driver_remove(struct i2c_client *client)
return -EINVAL;
}
+ CAM_INFO(CAM_OIS, "i2c driver remove invoked");
soc_info = &o_ctrl->soc_info;
for (i = 0; i < soc_info->num_clk; i++)
devm_clk_put(soc_info->dev, soc_info->clk[i]);
+ mutex_lock(&(o_ctrl->ois_mutex));
+ cam_ois_shutdown(o_ctrl);
+ mutex_unlock(&(o_ctrl->ois_mutex));
+ cam_unregister_subdev(&(o_ctrl->v4l2_dev_str));
+
soc_private =
(struct cam_ois_soc_private *)soc_info->soc_private;
power_info = &soc_private->power_info;
- kfree(power_info->power_setting);
- kfree(power_info->power_down_setting);
- power_info->power_setting = NULL;
- power_info->power_down_setting = NULL;
kfree(o_ctrl->soc_info.soc_private);
+ v4l2_set_subdevdata(&o_ctrl->v4l2_dev_str.sd, NULL);
kfree(o_ctrl);
return 0;
@@ -303,8 +306,6 @@ static int32_t cam_ois_platform_driver_probe(
o_ctrl->bridge_intf.device_hdl = -1;
platform_set_drvdata(pdev, o_ctrl);
- v4l2_set_subdevdata(&o_ctrl->v4l2_dev_str.sd, o_ctrl);
-
o_ctrl->cam_ois_state = CAM_OIS_INIT;
return rc;
@@ -333,21 +334,26 @@ static int cam_ois_platform_driver_remove(struct platform_device *pdev)
return -EINVAL;
}
+ CAM_INFO(CAM_OIS, "platform driver remove invoked");
soc_info = &o_ctrl->soc_info;
for (i = 0; i < soc_info->num_clk; i++)
devm_clk_put(soc_info->dev, soc_info->clk[i]);
+ mutex_lock(&(o_ctrl->ois_mutex));
+ cam_ois_shutdown(o_ctrl);
+ mutex_unlock(&(o_ctrl->ois_mutex));
+ cam_unregister_subdev(&(o_ctrl->v4l2_dev_str));
+
soc_private =
(struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private;
power_info = &soc_private->power_info;
- kfree(power_info->power_setting);
- kfree(power_info->power_down_setting);
- power_info->power_setting = NULL;
- power_info->power_down_setting = NULL;
kfree(o_ctrl->soc_info.soc_private);
kfree(o_ctrl->io_master_info.cci_client);
+ platform_set_drvdata(pdev, NULL);
+ v4l2_set_subdevdata(&o_ctrl->v4l2_dev_str.sd, NULL);
kfree(o_ctrl);
+
return 0;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_res_mgr/cam_res_mgr.c
index d03faef4d3a6..ed2f9ad945a5 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_res_mgr/cam_res_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_res_mgr/cam_res_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -178,8 +178,10 @@ int cam_res_mgr_shared_pinctrl_init(void)
return 0;
}
+ mutex_lock(&cam_res->gpio_res_lock);
if (cam_res->pstatus != PINCTRL_STATUS_PUT) {
CAM_DBG(CAM_RES, "The shared pinctrl already been got.");
+ mutex_unlock(&cam_res->gpio_res_lock);
return 0;
}
@@ -190,6 +192,7 @@ int cam_res_mgr_shared_pinctrl_init(void)
if (IS_ERR_OR_NULL(pinctrl_info->pinctrl)) {
CAM_ERR(CAM_RES, "Pinctrl not available");
cam_res->shared_gpio_enabled = false;
+ mutex_unlock(&cam_res->gpio_res_lock);
return -EINVAL;
}
@@ -200,6 +203,7 @@ int cam_res_mgr_shared_pinctrl_init(void)
CAM_ERR(CAM_RES,
"Failed to get the active state pinctrl handle");
cam_res->shared_gpio_enabled = false;
+ mutex_unlock(&cam_res->gpio_res_lock);
return -EINVAL;
}
@@ -210,10 +214,10 @@ int cam_res_mgr_shared_pinctrl_init(void)
CAM_ERR(CAM_RES,
"Failed to get the active state pinctrl handle");
cam_res->shared_gpio_enabled = false;
+ mutex_unlock(&cam_res->gpio_res_lock);
return -EINVAL;
}
- mutex_lock(&cam_res->gpio_res_lock);
cam_res->pstatus = PINCTRL_STATUS_GOT;
mutex_unlock(&cam_res->gpio_res_lock);
@@ -313,6 +317,7 @@ int cam_res_mgr_shared_pinctrl_select_state(bool active)
pinctrl_info->gpio_state_suspend);
cam_res->pstatus = PINCTRL_STATUS_SUSPEND;
}
+
mutex_unlock(&cam_res->gpio_res_lock);
return rc;
@@ -379,12 +384,14 @@ static bool cam_res_mgr_gpio_is_shared(uint gpio)
bool found = false;
struct cam_res_mgr_dt *dt = &cam_res->dt;
+ mutex_lock(&cam_res->gpio_res_lock);
for (; index < dt->num_shared_gpio; index++) {
if (gpio == dt->shared_gpio[index]) {
found = true;
break;
}
}
+ mutex_unlock(&cam_res->gpio_res_lock);
return found;
}
@@ -441,13 +448,14 @@ int cam_res_mgr_gpio_request(struct device *dev, uint gpio,
INIT_LIST_HEAD(&gpio_res->list);
INIT_LIST_HEAD(&gpio_res->dev_list);
+ mutex_lock(&cam_res->gpio_res_lock);
rc = cam_res_mgr_add_device(dev, gpio_res);
if (rc) {
kfree(gpio_res);
+ mutex_unlock(&cam_res->gpio_res_lock);
return rc;
}
- mutex_lock(&cam_res->gpio_res_lock);
list_add_tail(&gpio_res->list, &cam_res->gpio_res_list);
mutex_unlock(&cam_res->gpio_res_lock);
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c
index 2117cc1f9587..5f77ca0a5293 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -17,6 +17,8 @@
#include "cam_soc_util.h"
#include "cam_trace.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
+
static void cam_sensor_update_req_mgr(
struct cam_sensor_ctrl_t *s_ctrl,
@@ -94,6 +96,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
struct cam_cmd_buf_desc *cmd_desc = NULL;
struct i2c_settings_array *i2c_reg_settings = NULL;
size_t len_of_buff = 0;
+ size_t remain_len = 0;
uint32_t *offset = NULL;
struct cam_config_dev_cmd config;
struct i2c_data_settings *i2c_data = NULL;
@@ -115,27 +118,42 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
&generic_ptr,
&len_of_buff);
if (rc < 0) {
- CAM_ERR(CAM_SENSOR, "Failed in getting the buffer: %d", rc);
+ CAM_ERR(CAM_SENSOR, "Failed in getting the packet: %d", rc);
return rc;
}
+ remain_len = len_of_buff;
+ if ((sizeof(struct cam_packet) > len_of_buff) ||
+ ((size_t)config.offset >= len_of_buff -
+ sizeof(struct cam_packet))) {
+ CAM_ERR(CAM_SENSOR,
+ "Inval cam_packet strut size: %zu, len_of_buff: %zu",
+ sizeof(struct cam_packet), len_of_buff);
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+
+ remain_len -= (size_t)config.offset;
csl_packet = (struct cam_packet *)(generic_ptr +
(uint32_t)config.offset);
- if (config.offset > len_of_buff) {
- CAM_ERR(CAM_SENSOR,
- "offset is out of bounds: off: %lld len: %zu",
- config.offset, len_of_buff);
- return -EINVAL;
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_SENSOR, "Invalid packet params");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+
}
if ((csl_packet->header.op_code & 0xFFFFFF) !=
CAM_SENSOR_PACKET_OPCODE_SENSOR_INITIAL_CONFIG &&
csl_packet->header.request_id <= s_ctrl->last_flush_req
&& s_ctrl->last_flush_req != 0) {
- CAM_DBG(CAM_SENSOR,
- "reject request %lld, last request to flush %lld",
+ CAM_ERR(CAM_SENSOR,
+ "reject request %lld, last request to flush %u",
csl_packet->header.request_id, s_ctrl->last_flush_req);
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
if (csl_packet->header.request_id > s_ctrl->last_flush_req)
@@ -158,7 +176,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
}
case CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMON: {
if (s_ctrl->streamon_count > 0)
- return 0;
+ goto rel_pkt_buf;
s_ctrl->streamon_count = s_ctrl->streamon_count + 1;
i2c_reg_settings = &i2c_data->streamon_settings;
@@ -168,7 +186,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
}
case CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMOFF: {
if (s_ctrl->streamoff_count > 0)
- return 0;
+ goto rel_pkt_buf;
s_ctrl->streamoff_count = s_ctrl->streamoff_count + 1;
i2c_reg_settings = &i2c_data->streamoff_settings;
@@ -182,7 +200,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
(s_ctrl->sensor_state == CAM_SENSOR_ACQUIRE)) {
CAM_WARN(CAM_SENSOR,
"Rxed Update packets without linking");
- return 0;
+ goto rel_pkt_buf;
}
i2c_reg_settings =
@@ -202,7 +220,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
* fix it.
*/
cam_sensor_update_req_mgr(s_ctrl, csl_packet);
- return 0;
+ goto rel_pkt_buf;
}
break;
}
@@ -211,15 +229,16 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
(s_ctrl->sensor_state == CAM_SENSOR_ACQUIRE)) {
CAM_WARN(CAM_SENSOR,
"Rxed NOP packets without linking");
- return 0;
+ goto rel_pkt_buf;
}
cam_sensor_update_req_mgr(s_ctrl, csl_packet);
- return 0;
+ goto rel_pkt_buf;
}
default:
CAM_ERR(CAM_SENSOR, "Invalid Packet Header");
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
offset = (uint32_t *)&csl_packet->payload;
@@ -230,7 +249,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
i2c_reg_settings, cmd_desc, 1);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "Fail parsing I2C Pkt: %d", rc);
- return rc;
+ goto rel_pkt_buf;
}
if ((csl_packet->header.op_code & 0xFFFFFF) ==
@@ -240,6 +259,11 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
cam_sensor_update_req_mgr(s_ctrl, csl_packet);
}
+rel_pkt_buf:
+ if (cam_mem_put_cpu_buf(config.packet_handle))
+ CAM_WARN(CAM_SENSOR, "Failed in put the buffer: %llu",
+ config.packet_handle);
+
return rc;
}
@@ -359,7 +383,7 @@ int32_t cam_sensor_update_slave_info(struct cam_cmd_probe *probe_info,
int32_t cam_handle_cmd_buffers_for_probe(void *cmd_buf,
struct cam_sensor_ctrl_t *s_ctrl,
- int32_t cmd_buf_num, int cmd_buf_length)
+ int32_t cmd_buf_num, uint32_t cmd_buf_length, size_t remain_len)
{
int32_t rc = 0;
@@ -368,6 +392,13 @@ int32_t cam_handle_cmd_buffers_for_probe(void *cmd_buf,
struct cam_cmd_i2c_info *i2c_info = NULL;
struct cam_cmd_probe *probe_info;
+ if (remain_len <
+ (sizeof(struct cam_cmd_i2c_info) +
+ sizeof(struct cam_cmd_probe))) {
+ CAM_ERR(CAM_SENSOR,
+ "not enough buffer for cam_cmd_i2c_info");
+ return -EINVAL;
+ }
i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
rc = cam_sensor_update_i2c_info(i2c_info, s_ctrl);
if (rc < 0) {
@@ -386,7 +417,8 @@ int32_t cam_handle_cmd_buffers_for_probe(void *cmd_buf,
break;
case 1: {
rc = cam_sensor_update_power_settings(cmd_buf,
- cmd_buf_length, &s_ctrl->sensordata->power_info);
+ cmd_buf_length, &s_ctrl->sensordata->power_info,
+ remain_len);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"Failed in updating power settings");
@@ -407,10 +439,11 @@ int32_t cam_handle_mem_ptr(uint64_t handle, struct cam_sensor_ctrl_t *s_ctrl)
uint32_t *cmd_buf;
void *ptr;
size_t len;
- struct cam_packet *pkt;
- struct cam_cmd_buf_desc *cmd_desc;
+ struct cam_packet *pkt = NULL;
+ struct cam_cmd_buf_desc *cmd_desc = NULL;
uintptr_t cmd_buf1 = 0;
uintptr_t packet = 0;
+ size_t remain_len = 0;
rc = cam_mem_get_cpu_buf(handle,
&packet, &len);
@@ -418,18 +451,35 @@ int32_t cam_handle_mem_ptr(uint64_t handle, struct cam_sensor_ctrl_t *s_ctrl)
CAM_ERR(CAM_SENSOR, "Failed to get the command Buffer");
return -EINVAL;
}
+
pkt = (struct cam_packet *)packet;
+ if (pkt == NULL) {
+ CAM_ERR(CAM_SENSOR, "packet pos is invalid");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+
+ if ((len < sizeof(struct cam_packet)) ||
+ (pkt->cmd_buf_offset >= (len - sizeof(struct cam_packet)))) {
+ CAM_ERR(CAM_SENSOR, "Not enough buf provided");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+
cmd_desc = (struct cam_cmd_buf_desc *)
((uint32_t *)&pkt->payload + pkt->cmd_buf_offset/4);
if (cmd_desc == NULL) {
CAM_ERR(CAM_SENSOR, "command descriptor pos is invalid");
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
if (pkt->num_cmd_buf != 2) {
CAM_ERR(CAM_SENSOR, "Expected More Command Buffers : %d",
pkt->num_cmd_buf);
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
+
for (i = 0; i < pkt->num_cmd_buf; i++) {
if (!(cmd_desc[i].length))
continue;
@@ -438,20 +488,54 @@ int32_t cam_handle_mem_ptr(uint64_t handle, struct cam_sensor_ctrl_t *s_ctrl)
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"Failed to parse the command Buffer Header");
- return -EINVAL;
+ goto rel_pkt_buf;
+ }
+ if (cmd_desc[i].offset >= len) {
+ CAM_ERR(CAM_SENSOR,
+ "offset past length of buffer");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+ remain_len = len - cmd_desc[i].offset;
+ if (cmd_desc[i].length > remain_len) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer provided for cmd");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
cmd_buf = (uint32_t *)cmd_buf1;
cmd_buf += cmd_desc[i].offset/4;
ptr = (void *) cmd_buf;
rc = cam_handle_cmd_buffers_for_probe(ptr, s_ctrl,
- i, cmd_desc[i].length);
+ i, cmd_desc[i].length, remain_len);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"Failed to parse the command Buffer Header");
- return -EINVAL;
+ goto rel_cmd_buf;
}
+
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_SENSOR,
+ "Failed to put command Buffer : %d",
+ cmd_desc[i].mem_handle);
}
+
+ if (cam_mem_put_cpu_buf(handle))
+ CAM_WARN(CAM_SENSOR, "Failed to put the command Buffer: %llu",
+ handle);
+
+ return rc;
+
+rel_cmd_buf:
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_SENSOR, "Failed to put command Buffer : 0x%x",
+ cmd_desc[i].mem_handle);
+rel_pkt_buf:
+ if (cam_mem_put_cpu_buf(handle))
+ CAM_WARN(CAM_SENSOR, "Failed to put the command Buffer: %llu",
+ handle);
+
return rc;
}
@@ -507,11 +591,13 @@ void cam_sensor_shutdown(struct cam_sensor_ctrl_t *s_ctrl)
cam_sensor_release_stream_rsc(s_ctrl);
cam_sensor_release_per_frame_resource(s_ctrl);
- cam_sensor_power_down(s_ctrl);
+
+ if (s_ctrl->sensor_state != CAM_SENSOR_INIT)
+ cam_sensor_power_down(s_ctrl);
rc = cam_destroy_device_hdl(s_ctrl->bridge_intf.device_hdl);
if (rc < 0)
- CAM_ERR(CAM_SENSOR, " failed destroying dhdl");
+ CAM_ERR(CAM_SENSOR, "dhdl already destroyed: rc = %d", rc);
s_ctrl->bridge_intf.device_hdl = -1;
s_ctrl->bridge_intf.link_hdl = -1;
s_ctrl->bridge_intf.session_hdl = -1;
@@ -843,7 +929,7 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
case CAM_CONFIG_DEV: {
rc = cam_sensor_i2c_pkt_parse(s_ctrl, arg);
if (rc < 0) {
- CAM_ERR(CAM_SENSOR, "Failed CCI Config: %d", rc);
+ CAM_ERR(CAM_SENSOR, "Failed i2c pkt parse: %d", rc);
goto release_mutex;
}
if (s_ctrl->i2c_data.init_settings.is_settings_valid &&
@@ -1210,12 +1296,19 @@ int32_t cam_sensor_flush_request(struct cam_req_mgr_flush_request *flush_req)
return -EINVAL;
}
+ mutex_lock(&(s_ctrl->cam_sensor_mutex));
+ if (s_ctrl->sensor_state != CAM_SENSOR_START ||
+ s_ctrl->sensor_state != CAM_SENSOR_CONFIG) {
+ mutex_unlock(&(s_ctrl->cam_sensor_mutex));
+ return rc;
+ }
+
if (s_ctrl->i2c_data.per_frame == NULL) {
CAM_ERR(CAM_SENSOR, "i2c frame data is NULL");
+ mutex_unlock(&(s_ctrl->cam_sensor_mutex));
return -EINVAL;
}
- mutex_lock(&(s_ctrl->cam_sensor_mutex));
if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
s_ctrl->last_flush_req = flush_req->req_id;
CAM_DBG(CAM_SENSOR, "last reqest to flush is %lld",
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c
index 8dcb6c73312f..5c5c97099d43 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -199,7 +199,7 @@ static int32_t cam_sensor_driver_i2c_probe(struct i2c_client *client,
s_ctrl->bridge_intf.ops.flush_req = cam_sensor_flush_request;
s_ctrl->sensordata->power_info.dev = soc_info->dev;
- v4l2_set_subdevdata(&(s_ctrl->v4l2_dev_str.sd), s_ctrl);
+
return rc;
unreg_subdev:
cam_unregister_subdev(&(s_ctrl->v4l2_dev_str));
@@ -220,11 +220,18 @@ static int cam_sensor_platform_remove(struct platform_device *pdev)
return 0;
}
+ CAM_INFO(CAM_SENSOR, "platform remove invoked");
+ mutex_lock(&(s_ctrl->cam_sensor_mutex));
+ cam_sensor_shutdown(s_ctrl);
+ mutex_unlock(&(s_ctrl->cam_sensor_mutex));
+ cam_unregister_subdev(&(s_ctrl->v4l2_dev_str));
soc_info = &s_ctrl->soc_info;
for (i = 0; i < soc_info->num_clk; i++)
devm_clk_put(soc_info->dev, soc_info->clk[i]);
kfree(s_ctrl->i2c_data.per_frame);
+ platform_set_drvdata(pdev, NULL);
+ v4l2_set_subdevdata(&(s_ctrl->v4l2_dev_str.sd), NULL);
devm_kfree(&pdev->dev, s_ctrl);
return 0;
@@ -241,11 +248,17 @@ static int cam_sensor_driver_i2c_remove(struct i2c_client *client)
return 0;
}
+ CAM_INFO(CAM_SENSOR, "i2c remove invoked");
+ mutex_lock(&(s_ctrl->cam_sensor_mutex));
+ cam_sensor_shutdown(s_ctrl);
+ mutex_unlock(&(s_ctrl->cam_sensor_mutex));
+ cam_unregister_subdev(&(s_ctrl->v4l2_dev_str));
soc_info = &s_ctrl->soc_info;
for (i = 0; i < soc_info->num_clk; i++)
devm_clk_put(soc_info->dev, soc_info->clk[i]);
kfree(s_ctrl->i2c_data.per_frame);
+ v4l2_set_subdevdata(&(s_ctrl->v4l2_dev_str.sd), NULL);
kfree(s_ctrl);
return 0;
@@ -323,8 +336,6 @@ static int32_t cam_sensor_driver_platform_probe(
s_ctrl->sensordata->power_info.dev = &pdev->dev;
platform_set_drvdata(pdev, s_ctrl);
- v4l2_set_subdevdata(&(s_ctrl->v4l2_dev_str.sd), s_ctrl);
-
s_ctrl->sensor_state = CAM_SENSOR_INIT;
return rc;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
index 1e9ec3db054a..7a2c56e3b686 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -325,6 +325,9 @@ enum msm_sensor_camera_id_t {
CAMERA_1,
CAMERA_2,
CAMERA_3,
+ CAMERA_4,
+ CAMERA_5,
+ CAMERA_6,
MAX_CAMERAS,
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
index 713bcaa8643a..7f6f3aa40998 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -298,6 +298,8 @@ int cam_sensor_i2c_command_parser(
size_t len_of_buff = 0;
uintptr_t generic_ptr;
uint16_t cmd_length_in_bytes = 0;
+ size_t remain_len = 0;
+ size_t tot_size = 0;
for (i = 0; i < num_cmd_buffers; i++) {
uint32_t *cmd_buf = NULL;
@@ -319,16 +321,35 @@ int cam_sensor_i2c_command_parser(
rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
&generic_ptr, &len_of_buff);
- cmd_buf = (uint32_t *)generic_ptr;
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"cmd hdl failed:%d, Err: %d, Buffer_len: %zd",
cmd_desc[i].mem_handle, rc, len_of_buff);
return rc;
}
+
+ remain_len = len_of_buff;
+ if ((len_of_buff < sizeof(struct common_header)) ||
+ (cmd_desc[i].offset >
+ (len_of_buff - sizeof(struct common_header)))) {
+ CAM_ERR(CAM_SENSOR, "buffer provided too small");
+ return -EINVAL;
+ }
+ cmd_buf = (uint32_t *)generic_ptr;
cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
+ if (remain_len < cmd_desc[i].length) {
+ CAM_ERR(CAM_SENSOR, "buffer provided too small");
+ return -EINVAL;
+ }
+
while (byte_cnt < cmd_desc[i].length) {
+ if ((remain_len - byte_cnt) <
+ sizeof(struct common_header)) {
+ CAM_ERR(CAM_SENSOR, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_buf;
+ }
cmm_hdr = (struct common_header *)cmd_buf;
generic_op_code = cmm_hdr->third_byte;
switch (cmm_hdr->cmd_type) {
@@ -338,6 +359,24 @@ int cam_sensor_i2c_command_parser(
*cam_cmd_i2c_random_wr =
(struct cam_cmd_i2c_random_wr *)cmd_buf;
+ if ((remain_len - byte_cnt) <
+ sizeof(struct cam_cmd_i2c_random_wr)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer provided");
+ rc = -EINVAL;
+ goto rel_buf;
+ }
+ tot_size = sizeof(struct i2c_rdwr_header) +
+ (sizeof(struct i2c_random_wr_payload) *
+ cam_cmd_i2c_random_wr->header.count);
+
+ if (tot_size > (remain_len - byte_cnt)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer provided");
+ rc = -EINVAL;
+ goto rel_buf;
+ }
+
rc = cam_sensor_handle_random_write(
cam_cmd_i2c_random_wr,
i2c_reg_settings,
@@ -345,7 +384,7 @@ int cam_sensor_i2c_command_parser(
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"Failed in random write %d", rc);
- return rc;
+ return -EINVAL;
}
cmd_buf += cmd_length_in_bytes /
@@ -360,6 +399,24 @@ int cam_sensor_i2c_command_parser(
(struct cam_cmd_i2c_continuous_wr *)
cmd_buf;
+ if ((remain_len - byte_cnt) <
+ sizeof(struct cam_cmd_i2c_continuous_wr)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer provided");
+ return -EINVAL;
+ }
+
+ tot_size = sizeof(struct i2c_rdwr_header) +
+ sizeof(cam_cmd_i2c_continuous_wr->reg_addr) +
+ (sizeof(struct cam_cmd_read) *
+ cam_cmd_i2c_continuous_wr->header.count);
+
+ if (tot_size > (remain_len - byte_cnt)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer provided");
+ return -EINVAL;
+ }
+
rc = cam_sensor_handle_continuous_write(
cam_cmd_i2c_continuous_wr,
i2c_reg_settings,
@@ -376,11 +433,16 @@ int cam_sensor_i2c_command_parser(
break;
}
case CAMERA_SENSOR_CMD_TYPE_WAIT: {
+ if ((remain_len - byte_cnt) <
+ sizeof(struct cam_cmd_unconditional_wait)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer space");
+ return -EINVAL;
+ }
if (generic_op_code ==
CAMERA_SENSOR_WAIT_OP_HW_UCND ||
generic_op_code ==
CAMERA_SENSOR_WAIT_OP_SW_UCND) {
-
rc = cam_sensor_handle_delay(
&cmd_buf, generic_op_code,
i2c_reg_settings, j, &byte_cnt,
@@ -412,13 +474,20 @@ int cam_sensor_i2c_command_parser(
break;
}
case CAMERA_SENSOR_CMD_TYPE_I2C_INFO: {
+ if (remain_len - byte_cnt <
+ sizeof(struct cam_cmd_i2c_info)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer space");
+ rc = -EINVAL;
+ goto rel_buf;
+ }
rc = cam_sensor_handle_slave_info(
io_master, cmd_buf);
if (rc) {
CAM_ERR(CAM_SENSOR,
- "Handle slave info failed with rc: %d",
- rc);
- return rc;
+ "Handle slave info failed with rc: %d",
+ rc);
+ goto rel_buf;
}
cmd_length_in_bytes =
sizeof(struct cam_cmd_i2c_info);
@@ -430,13 +499,23 @@ int cam_sensor_i2c_command_parser(
default:
CAM_ERR(CAM_SENSOR, "Invalid Command Type:%d",
cmm_hdr->cmd_type);
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_buf;
}
}
i2c_reg_settings->is_settings_valid = 1;
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_SENSOR, "put failed for buffer :%d",
+ cmd_desc[i].mem_handle);
}
return rc;
+
+rel_buf:
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_SENSOR, "put failed for buffer :%d",
+ cmd_desc[i].mem_handle);
+ return rc;
}
int cam_sensor_util_i2c_apply_setting(
@@ -750,8 +829,32 @@ int cam_sensor_util_request_gpio_table(
return rc;
}
+
+static int32_t cam_sensor_validate(void *ptr, size_t remain_buf)
+{
+ struct common_header *cmm_hdr = (struct common_header *)ptr;
+ size_t validate_size = 0;
+
+ if (remain_buf < sizeof(struct common_header))
+ return -EINVAL;
+
+ if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_PWR_UP ||
+ cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_PWR_DOWN)
+ validate_size = sizeof(struct cam_cmd_power);
+ else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT)
+ validate_size = sizeof(struct cam_cmd_unconditional_wait);
+
+ if (remain_buf < validate_size) {
+ CAM_ERR(CAM_SENSOR, "Invalid cmd_buf len %zu min %zu",
+ remain_buf, validate_size);
+ return -EINVAL;
+ }
+ return 0;
+}
+
int32_t cam_sensor_update_power_settings(void *cmd_buf,
- int cmd_length, struct cam_sensor_power_ctrl_t *power_info)
+ uint32_t cmd_length, struct cam_sensor_power_ctrl_t *power_info,
+ size_t cmd_buf_len)
{
int32_t rc = 0, tot_size = 0, last_cmd_type = 0;
int32_t i = 0, pwr_up = 0, pwr_down = 0;
@@ -760,7 +863,8 @@ int32_t cam_sensor_update_power_settings(void *cmd_buf,
struct cam_cmd_power *pwr_cmd = (struct cam_cmd_power *)cmd_buf;
struct common_header *cmm_hdr = (struct common_header *)cmd_buf;
- if (!pwr_cmd || !cmd_length) {
+ if (!pwr_cmd || !cmd_length || cmd_buf_len < (size_t)cmd_length ||
+ cam_sensor_validate(cmd_buf, cmd_buf_len)) {
CAM_ERR(CAM_SENSOR, "Invalid Args: pwr_cmd %pK, cmd_length: %d",
pwr_cmd, cmd_length);
return -EINVAL;
@@ -787,16 +891,29 @@ int32_t cam_sensor_update_power_settings(void *cmd_buf,
}
while (tot_size < cmd_length) {
+ if (cam_sensor_validate(ptr, (cmd_length - tot_size))) {
+ rc = -EINVAL;
+ goto free_power_settings;
+ }
if (cmm_hdr->cmd_type ==
CAMERA_SENSOR_CMD_TYPE_PWR_UP) {
struct cam_cmd_power *pwr_cmd =
(struct cam_cmd_power *)ptr;
+ if ((U16_MAX - power_info->power_setting_size) <
+ pwr_cmd->count) {
+ CAM_ERR(CAM_SENSOR, "ERR: Overflow occurs");
+ rc = -EINVAL;
+ goto free_power_settings;
+ }
+
power_info->power_setting_size += pwr_cmd->count;
- if (power_info->power_setting_size > MAX_POWER_CONFIG) {
+ if ((power_info->power_setting_size > MAX_POWER_CONFIG)
+ || (pwr_cmd->count >= SENSOR_SEQ_TYPE_MAX)) {
CAM_ERR(CAM_SENSOR,
- "Invalid: power up setting size %d",
- power_info->power_setting_size);
+ "pwr_up setting size %d, pwr_cmd->count: %d",
+ power_info->power_setting_size,
+ pwr_cmd->count);
rc = -EINVAL;
goto free_power_settings;
}
@@ -891,12 +1008,21 @@ int32_t cam_sensor_update_power_settings(void *cmd_buf,
scr = ptr + sizeof(struct cam_cmd_power);
tot_size = tot_size + sizeof(struct cam_cmd_power);
+ if ((U16_MAX - power_info->power_down_setting_size) <
+ pwr_cmd->count) {
+ CAM_ERR(CAM_SENSOR, "ERR: Overflow");
+ rc = -EINVAL;
+ goto free_power_settings;
+ }
+
power_info->power_down_setting_size += pwr_cmd->count;
- if (power_info->power_down_setting_size >
- MAX_POWER_CONFIG) {
+ if ((power_info->power_down_setting_size >
+ MAX_POWER_CONFIG) || (pwr_cmd->count >=
+ SENSOR_SEQ_TYPE_MAX)) {
CAM_ERR(CAM_SENSOR,
- "Invalid: power down setting size %d",
- power_info->power_down_setting_size);
+ "pwr_down_setting_size %d, pwr_cmd->count: %d",
+ power_info->power_down_setting_size,
+ pwr_cmd->count);
rc = -EINVAL;
goto free_power_settings;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
index 583ddb14243b..85497fda011c 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -60,7 +60,8 @@ int msm_camera_fill_vreg_params(struct cam_hw_soc_info *soc_info,
uint16_t power_setting_size);
int32_t cam_sensor_update_power_settings(void *cmd_buf,
- int cmd_length, struct cam_sensor_power_ctrl_t *power_info);
+ uint32_t cmd_length, struct cam_sensor_power_ctrl_t *power_info,
+ size_t cmd_buf_len);
int cam_sensor_bob_pwm_mode_switch(struct cam_hw_soc_info *soc_info,
int bob_reg_idx, bool flag);
diff --git a/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c b/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c
index 7a772f1c4269..1be244bb7c3a 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -196,8 +196,8 @@ int cam_sync_signal(int32_t sync_obj, uint32_t status)
if (row->state != CAM_SYNC_STATE_ACTIVE) {
spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
CAM_ERR(CAM_SYNC,
- "Error: Sync object already signaled sync_obj = %d",
- sync_obj);
+ "Sync object already signaled sync_obj = %d state = %d",
+ sync_obj, row->state);
return -EALREADY;
}
@@ -323,8 +323,8 @@ int cam_sync_get_obj_ref(int32_t sync_obj)
if (row->state != CAM_SYNC_STATE_ACTIVE) {
spin_unlock(&sync_dev->row_spinlocks[sync_obj]);
CAM_ERR(CAM_SYNC,
- "Error: accessing an uninitialized sync obj = %d",
- sync_obj);
+ "accessing an uninitialized sync obj = %d state = %d",
+ sync_obj, row->state);
return -EINVAL;
}
@@ -433,6 +433,7 @@ static int cam_sync_handle_create(struct cam_private_ioctl_arg *k_ioctl)
static int cam_sync_handle_signal(struct cam_private_ioctl_arg *k_ioctl)
{
+ int rc = 0;
struct cam_sync_signal sync_signal;
if (k_ioctl->size != sizeof(struct cam_sync_signal))
@@ -447,7 +448,14 @@ static int cam_sync_handle_signal(struct cam_private_ioctl_arg *k_ioctl)
return -EFAULT;
/* need to get ref for UMD signaled fences */
- cam_sync_get_obj_ref(sync_signal.sync_obj);
+ rc = cam_sync_get_obj_ref(sync_signal.sync_obj);
+ if (rc) {
+ CAM_DBG(CAM_SYNC,
+ "Error: cannot signal an uninitialized sync obj = %d",
+ sync_signal.sync_obj);
+ return rc;
+ }
+
return cam_sync_signal(sync_signal.sync_obj,
sync_signal.sync_state);
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/Makefile b/drivers/media/platform/msm/camera_v3/cam_utils/Makefile
index 7e1ebd3b7c64..9b14dfb9f6a4 100644
--- a/drivers/media/platform/msm/camera_v3/cam_utils/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/Makefile
@@ -3,3 +3,4 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_req_mgr/
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_smmu/
obj-$(CONFIG_SPECTRA_CAMERA) += cam_soc_util.o cam_io_util.o cam_packet_util.o cam_debug_util.o cam_trace.o cam_common_util.o
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_cx_ipeak.o
diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_cx_ipeak.c b/drivers/media/platform/msm/camera_v3/cam_utils/cam_cx_ipeak.c
new file mode 100644
index 000000000000..99de0cba82ad
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_cx_ipeak.c
@@ -0,0 +1,135 @@
+/* Copyright (c) 2018, 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <soc/qcom/cx_ipeak.h>
+#include "cam_soc_util.h"
+#include "cam_debug_util.h"
+
+static struct cx_ipeak_client *cam_cx_ipeak;
+static int cx_ipeak_level = CAM_NOMINAL_VOTE;
+static int cx_default_ipeak_mask;
+static int cx_current_ipeak_mask;
+static int cam_cx_client_cnt;
+
+int cam_cx_ipeak_register_cx_ipeak(struct cam_hw_soc_info *soc_info)
+{
+ int rc = 0;
+
+ soc_info->cam_cx_ipeak_enable = true;
+ soc_info->cam_cx_ipeak_bit = 1 << cam_cx_client_cnt++;
+ cx_default_ipeak_mask |= soc_info->cam_cx_ipeak_bit;
+
+ if (cam_cx_ipeak)
+ goto exit;
+
+ cam_cx_ipeak = cx_ipeak_register(soc_info->dev->of_node,
+ "qcom,cam-cx-ipeak");
+
+ if (cam_cx_ipeak) {
+ goto exit;
+ } else {
+ rc = -EINVAL;
+ goto exit;
+ }
+
+exit:
+ CAM_DBG(CAM_UTIL, "cam_cx_ipeak is enabled for %s\n"
+ "mask = %x cx_default_ipeak_mask = %x",
+ soc_info->dev_name, soc_info->cam_cx_ipeak_bit,
+ cx_default_ipeak_mask);
+ return rc;
+}
+
+int cam_cx_ipeak_update_vote_cx_ipeak(struct cam_hw_soc_info *soc_info,
+ int32_t apply_level)
+{
+ int32_t soc_cx_ipeak_bit = soc_info->cam_cx_ipeak_bit;
+ int ret = 0;
+
+ CAM_DBG(CAM_UTIL, "E: apply_level = %d cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x",
+ apply_level, cx_current_ipeak_mask, soc_cx_ipeak_bit);
+
+ if (apply_level < cx_ipeak_level &&
+ (cx_current_ipeak_mask & soc_cx_ipeak_bit)) {
+ if (cx_current_ipeak_mask == cx_default_ipeak_mask) {
+ ret = cx_ipeak_update(cam_cx_ipeak, false);
+ if (ret)
+ goto exit;
+ CAM_DBG(CAM_UTIL,
+ "X: apply_level = %d cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x %s UNVOTE",
+ apply_level, cx_current_ipeak_mask,
+ soc_cx_ipeak_bit, soc_info->dev_name);
+ }
+ cx_current_ipeak_mask &= (~soc_cx_ipeak_bit);
+ CAM_DBG(CAM_UTIL,
+ "X: apply_level = %d cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x %s DISABLE_BIT",
+ apply_level, cx_current_ipeak_mask,
+ soc_cx_ipeak_bit, soc_info->dev_name);
+ goto exit;
+ } else if (apply_level < cx_ipeak_level) {
+ CAM_DBG(CAM_UTIL,
+ "X: apply_level = %d cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x NO AI",
+ apply_level, cx_current_ipeak_mask, soc_cx_ipeak_bit);
+ goto exit;
+ }
+
+ cx_current_ipeak_mask |= soc_cx_ipeak_bit;
+ CAM_DBG(CAM_UTIL,
+ "X: apply_level = %d cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x %s ENABLE_BIT",
+ apply_level, cx_current_ipeak_mask,
+ soc_cx_ipeak_bit, soc_info->dev_name);
+ if (cx_current_ipeak_mask == cx_default_ipeak_mask) {
+ ret = cx_ipeak_update(cam_cx_ipeak, true);
+ if (ret)
+ goto exit;
+ CAM_DBG(CAM_UTIL,
+ "X: apply_level = %d cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x %s VOTE",
+ apply_level, cx_current_ipeak_mask,
+ soc_cx_ipeak_bit, soc_info->dev_name);
+ }
+
+exit:
+ return ret;
+}
+
+int cam_cx_ipeak_unvote_cx_ipeak(struct cam_hw_soc_info *soc_info)
+{
+ int32_t soc_cx_ipeak_bit = soc_info->cam_cx_ipeak_bit;
+
+ CAM_DBG(CAM_UTIL, "E:cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x",
+ cx_current_ipeak_mask, soc_cx_ipeak_bit);
+ if (cx_current_ipeak_mask == cx_default_ipeak_mask) {
+ if (cam_cx_ipeak)
+ cx_ipeak_update(cam_cx_ipeak, false);
+ CAM_DBG(CAM_UTIL, "X:cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x UNVOTE",
+ cx_current_ipeak_mask, soc_cx_ipeak_bit);
+ }
+ cx_current_ipeak_mask &= (~soc_cx_ipeak_bit);
+ CAM_DBG(CAM_UTIL, "X:cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x",
+ cx_current_ipeak_mask, soc_cx_ipeak_bit);
+
+ return 0;
+}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_log.h b/drivers/media/platform/msm/camera_v3/cam_utils/cam_cx_ipeak.h
index 321248a3e0eb..f811ac549429 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_log.h
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_cx_ipeak.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, 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
@@ -10,17 +10,17 @@
* GNU General Public License for more details.
*/
-#ifndef _CAM_ISP_LOG_H_
-#define _CAM_ISP_LOG_H_
+#ifndef _CAM_CX_IPEAK_H_
+#define _CAM_CX_IPEAK_H_
-#include <linux/kernel.h>
+#include <linux/clk/qcom.h>
+#include <soc/qcom/cx_ipeak.h>
+#include "cam_io_util.h"
-#define ISP_TRACE_ENABLE 1
+int cam_cx_ipeak_register_cx_ipeak(struct cam_hw_soc_info *soc_info);
-#if (ISP_TRACE_ENABLE == 1)
- #define ISP_TRACE(args...) trace_printk(args)
-#else
- #define ISP_TRACE(arg...)
-#endif
+int cam_cx_ipeak_update_vote_cx_ipeak(struct cam_hw_soc_info *soc_info,
+ int32_t apply_level);
+int cam_cx_ipeak_unvote_cx_ipeak(struct cam_hw_soc_info *soc_info);
-#endif /* __CAM_ISP_LOG_H__ */
+#endif /* _CAM_CX_IPEAK_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.c b/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.c
index acfae3622130..f623369dd857 100644
--- a/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.c
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -50,23 +50,44 @@ int cam_packet_util_validate_cmd_desc(struct cam_cmd_buf_desc *cmd_desc)
return 0;
}
-int cam_packet_util_validate_packet(struct cam_packet *packet)
+int cam_packet_util_validate_packet(struct cam_packet *packet,
+ size_t remain_len)
{
+ size_t sum_cmd_desc = 0;
+ size_t sum_io_cfgs = 0;
+ size_t sum_patch_desc = 0;
+ size_t pkt_wo_payload = 0;
+
if (!packet)
return -EINVAL;
+ if ((size_t)packet->header.size > remain_len) {
+ CAM_ERR(CAM_UTIL,
+ "Invalid packet size: %zu, CPU buf length: %zu",
+ (size_t)packet->header.size, remain_len);
+ return -EINVAL;
+ }
+
+
CAM_DBG(CAM_UTIL, "num cmd buf:%d num of io config:%d kmd buf index:%d",
packet->num_cmd_buf, packet->num_io_configs,
packet->kmd_cmd_buf_index);
- if ((packet->kmd_cmd_buf_index >= packet->num_cmd_buf) ||
- (!packet->header.size) ||
- (packet->cmd_buf_offset > packet->header.size) ||
- (packet->io_configs_offset > packet->header.size)) {
- CAM_ERR(CAM_UTIL, "invalid packet:%d %d %d %d %d",
- packet->kmd_cmd_buf_index,
- packet->num_cmd_buf, packet->cmd_buf_offset,
- packet->io_configs_offset, packet->header.size);
+ sum_cmd_desc = packet->num_cmd_buf * sizeof(struct cam_cmd_buf_desc);
+ sum_io_cfgs = packet->num_io_configs * sizeof(struct cam_buf_io_cfg);
+ sum_patch_desc = packet->num_patches * sizeof(struct cam_patch_desc);
+ pkt_wo_payload = offsetof(struct cam_packet, payload);
+
+ if ((!packet->header.size) ||
+ ((pkt_wo_payload + (size_t)packet->cmd_buf_offset +
+ sum_cmd_desc) > (size_t)packet->header.size) ||
+ ((pkt_wo_payload + (size_t)packet->io_configs_offset +
+ sum_io_cfgs) > (size_t)packet->header.size) ||
+ ((pkt_wo_payload + (size_t)packet->patch_offset +
+ sum_patch_desc) > (size_t)packet->header.size)) {
+ CAM_ERR(CAM_UTIL, "params not within mem len:%zu %zu %zu %zu",
+ (size_t)packet->header.size, sum_cmd_desc,
+ sum_io_cfgs, sum_patch_desc);
return -EINVAL;
}
@@ -78,6 +99,7 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
{
int rc = 0;
size_t len = 0;
+ size_t remain_len = 0;
struct cam_cmd_buf_desc *cmd_desc;
uint32_t *cpu_addr;
@@ -86,6 +108,13 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
return -EINVAL;
}
+ if ((packet->kmd_cmd_buf_index < 0) ||
+ (packet->kmd_cmd_buf_index > packet->num_cmd_buf)) {
+ CAM_ERR(CAM_UTIL, "Invalid kmd buf index: %d",
+ packet->kmd_cmd_buf_index);
+ return -EINVAL;
+ }
+
/* Take first command descriptor and add offset to it for kmd*/
cmd_desc = (struct cam_cmd_buf_desc *) ((uint8_t *)
&packet->payload + packet->cmd_buf_offset);
@@ -100,12 +129,21 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
if (rc)
return rc;
- if (len < cmd_desc->size) {
+ remain_len = len;
+ if (((size_t)cmd_desc->offset >= len) ||
+ ((size_t)cmd_desc->size >= (len - (size_t)cmd_desc->offset))) {
CAM_ERR(CAM_UTIL, "invalid memory len:%zd and cmd desc size:%d",
len, cmd_desc->size);
return -EINVAL;
}
+ remain_len -= (size_t)cmd_desc->offset;
+ if ((size_t)packet->kmd_cmd_buf_offset >= remain_len) {
+ CAM_ERR(CAM_UTIL, "Invalid kmd cmd buf offset: %zu",
+ (size_t)packet->kmd_cmd_buf_offset);
+ return -EINVAL;
+ }
+
cpu_addr += (cmd_desc->offset / 4) + (packet->kmd_cmd_buf_offset / 4);
CAM_DBG(CAM_UTIL, "total size %d, cmd size: %d, KMD buffer size: %d",
cmd_desc->size, cmd_desc->length,
@@ -128,7 +166,7 @@ int cam_packet_util_process_patches(struct cam_packet *packet,
{
struct cam_patch_desc *patch_desc = NULL;
dma_addr_t iova_addr;
- uintptr_t cpu_addr;
+ uintptr_t cpu_addr = 0;
uint32_t temp;
uint32_t *dst_cpu_addr;
uint32_t *src_buf_iova_addr;
@@ -147,7 +185,6 @@ int cam_packet_util_process_patches(struct cam_packet *packet,
sizeof(struct cam_patch_desc));
for (i = 0; i < packet->num_patches; i++) {
-
hdl = cam_mem_is_secure_buf(patch_desc[i].src_buf_hdl) ?
sec_mmu_hdl : iommu_hdl;
rc = cam_mem_get_io_buf(patch_desc[i].src_buf_hdl,
@@ -161,7 +198,7 @@ int cam_packet_util_process_patches(struct cam_packet *packet,
rc = cam_mem_get_cpu_buf(patch_desc[i].dst_buf_hdl,
&cpu_addr, &dst_buf_len);
- if (rc < 0) {
+ if (rc < 0 || !cpu_addr || (dst_buf_len == 0)) {
CAM_ERR(CAM_UTIL, "unable to get dst buf address");
return rc;
}
@@ -171,6 +208,20 @@ int cam_packet_util_process_patches(struct cam_packet *packet,
patch_desc[i].dst_buf_hdl, patch_desc[i].dst_offset,
patch_desc[i].src_buf_hdl, patch_desc[i].src_offset);
+ if ((size_t)patch_desc[i].src_offset >= src_buf_size) {
+ CAM_ERR(CAM_UTIL,
+ "Invalid src buf patch offset");
+ return -EINVAL;
+ }
+
+ if ((dst_buf_len < sizeof(void *)) ||
+ ((dst_buf_len - sizeof(void *)) <
+ (size_t)patch_desc[i].dst_offset)) {
+ CAM_ERR(CAM_UTIL,
+ "Invalid dst buf patch offset");
+ return -EINVAL;
+ }
+
dst_cpu_addr = (uint32_t *)((uint8_t *)dst_cpu_addr +
patch_desc[i].dst_offset);
temp += patch_desc[i].src_offset;
@@ -191,8 +242,9 @@ int cam_packet_util_process_generic_cmd_buffer(
cam_packet_generic_blob_handler blob_handler_cb, void *user_data)
{
int rc;
- uintptr_t cpu_addr;
+ uintptr_t cpu_addr = 0;
size_t buf_size;
+ size_t remain_len = 0;
uint32_t *blob_ptr;
uint32_t blob_type, blob_size, blob_block_size, len_read;
@@ -215,6 +267,21 @@ int cam_packet_util_process_generic_cmd_buffer(
return rc;
}
+ remain_len = buf_size;
+ if ((buf_size < sizeof(uint32_t)) ||
+ ((size_t)cmd_buf->offset > (buf_size - sizeof(uint32_t)))) {
+ CAM_ERR(CAM_UTIL, "Invalid offset for cmd buf: %zu",
+ (size_t)cmd_buf->offset);
+ return -EINVAL;
+ }
+
+ remain_len -= (size_t)cmd_buf->offset;
+ if (remain_len < (size_t)cmd_buf->length) {
+ CAM_ERR(CAM_UTIL, "Invalid length for cmd buf: %zu",
+ (size_t)cmd_buf->length);
+ return -EINVAL;
+ }
+
blob_ptr = (uint32_t *)(((uint8_t *)cpu_addr) +
cmd_buf->offset);
diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.h b/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.h
index b2315232262d..412eba52b05a 100644
--- a/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.h
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, 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
@@ -37,6 +37,9 @@ struct cam_kmd_buf_info {
typedef int (*cam_packet_generic_blob_handler)(void *user_data,
uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data);
+/* set resource bitmap callback function type */
+typedef void (*cam_fill_res_bitmap)(uint32_t res_type, unsigned long *bitmap);
+
/**
* cam_packet_util_get_cmd_mem_addr()
*
@@ -59,10 +62,13 @@ int cam_packet_util_get_cmd_mem_addr(int handle, uint32_t **buf_addr,
*
* @packet: Packet to be validated
*
+ * @remain_len: CPU buff length after config offset
+ *
* @return: 0 for success
* -EINVAL for Fail
*/
-int cam_packet_util_validate_packet(struct cam_packet *packet);
+int cam_packet_util_validate_packet(struct cam_packet *packet,
+ size_t remain_len);
/**
* cam_packet_util_validate_cmd_desc()
diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.c b/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.c
index 4972a2a8cd08..59a33889c013 100644
--- a/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.c
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, 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
@@ -18,6 +18,7 @@
#include <soc/qcom/socinfo.h>
#include "cam_soc_util.h"
#include "cam_debug_util.h"
+#include "cam_cx_ipeak.h"
#include <linux/nvmem-consumer.h>
uint32_t cam_soc_util_get_soc_id(void)
@@ -75,6 +76,33 @@ uint32_t cam_soc_util_get_hw_revision_node(struct cam_hw_soc_info *soc_info)
static char supported_clk_info[256];
static char debugfs_dir_name[64];
+static int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info,
+ int32_t src_clk_idx, int32_t clk_rate)
+{
+ int i;
+ long clk_rate_round;
+
+ clk_rate_round = clk_round_rate(soc_info->clk[src_clk_idx], clk_rate);
+ if (clk_rate_round < 0) {
+ CAM_ERR(CAM_UTIL, "round failed rc = %ld",
+ clk_rate_round);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < CAM_MAX_VOTE; i++) {
+ if (soc_info->clk_rate[i][src_clk_idx] >= clk_rate_round) {
+ CAM_DBG(CAM_UTIL,
+ "soc = %d round rate = %ld actual = %d",
+ soc_info->clk_rate[i][src_clk_idx],
+ clk_rate_round, clk_rate);
+ return i;
+ }
+ }
+
+ CAM_WARN(CAM_UTIL, "Invalid clock rate %ld", clk_rate_round);
+ return -EINVAL;
+}
+
/**
* cam_soc_util_get_string_from_level()
*
@@ -461,6 +489,7 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
{
int32_t src_clk_idx;
struct clk *clk = NULL;
+ int32_t apply_level;
if (!soc_info || (soc_info->src_clk_idx < 0))
return -EINVAL;
@@ -471,6 +500,17 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
src_clk_idx = soc_info->src_clk_idx;
clk = soc_info->clk[src_clk_idx];
+ if (soc_info->cam_cx_ipeak_enable && clk_rate >= 0) {
+ apply_level = cam_soc_util_get_clk_level(soc_info, src_clk_idx,
+ clk_rate);
+ CAM_DBG(CAM_UTIL, "set %s, rate %d dev_name = %s\n"
+ "apply level = %d",
+ soc_info->clk_name[src_clk_idx], clk_rate,
+ soc_info->dev_name, apply_level);
+ if (apply_level >= 0)
+ cam_cx_ipeak_update_vote_cx_ipeak(soc_info,
+ apply_level);
+ }
return cam_soc_util_set_clk_rate(clk,
soc_info->clk_name[src_clk_idx], clk_rate);
@@ -623,17 +663,29 @@ int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info,
if (rc)
return rc;
+ if (soc_info->cam_cx_ipeak_enable)
+ cam_cx_ipeak_update_vote_cx_ipeak(soc_info, apply_level);
+
for (i = 0; i < soc_info->num_clk; i++) {
rc = cam_soc_util_clk_enable(soc_info->clk[i],
soc_info->clk_name[i],
soc_info->clk_rate[apply_level][i]);
if (rc)
goto clk_disable;
+ if (soc_info->cam_cx_ipeak_enable) {
+ CAM_DBG(CAM_UTIL,
+ "dev name = %s clk name = %s idx = %d\n"
+ "apply_level = %d clc idx = %d",
+ soc_info->dev_name, soc_info->clk_name[i], i,
+ apply_level, i);
+ }
}
return rc;
clk_disable:
+ if (soc_info->cam_cx_ipeak_enable)
+ cam_cx_ipeak_update_vote_cx_ipeak(soc_info, 0);
for (i--; i >= 0; i--) {
cam_soc_util_clk_disable(soc_info->clk[i],
soc_info->clk_name[i]);
@@ -659,6 +711,8 @@ void cam_soc_util_clk_disable_default(struct cam_hw_soc_info *soc_info)
if (soc_info->num_clk == 0)
return;
+ if (soc_info->cam_cx_ipeak_enable)
+ cam_cx_ipeak_unvote_cx_ipeak(soc_info);
for (i = soc_info->num_clk - 1; i >= 0; i--)
cam_soc_util_clk_disable(soc_info->clk[i],
soc_info->clk_name[i]);
@@ -700,7 +754,8 @@ static int cam_soc_util_get_dt_clk_info(struct cam_hw_soc_info *soc_info)
count = of_property_count_strings(of_node, "clock-names");
- CAM_DBG(CAM_UTIL, "count = %d", count);
+ CAM_DBG(CAM_UTIL, "E: dev_name = %s count = %d",
+ soc_info->dev_name, count);
if (count > CAM_SOC_MAX_CLK) {
CAM_ERR(CAM_UTIL, "invalid count of clocks, count=%d", count);
rc = -EINVAL;
@@ -819,6 +874,8 @@ static int cam_soc_util_get_dt_clk_info(struct cam_hw_soc_info *soc_info)
if (strcmp("true", clk_control_debugfs) == 0)
soc_info->clk_control_enable = true;
+ CAM_DBG(CAM_UTIL, "X: dev_name = %s count = %d",
+ soc_info->dev_name, count);
end:
return rc;
}
@@ -841,12 +898,23 @@ int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info,
if (rc)
return rc;
+ if (soc_info->cam_cx_ipeak_enable)
+ cam_cx_ipeak_update_vote_cx_ipeak(soc_info, apply_level);
+
for (i = 0; i < soc_info->num_clk; i++) {
rc = cam_soc_util_set_clk_rate(soc_info->clk[i],
soc_info->clk_name[i],
soc_info->clk_rate[apply_level][i]);
- if (rc)
+ if (rc < 0) {
+ CAM_DBG(CAM_UTIL,
+ "dev name = %s clk_name = %s idx = %d\n"
+ "apply_level = %d",
+ soc_info->dev_name, soc_info->clk_name[i],
+ i, apply_level);
+ if (soc_info->cam_cx_ipeak_enable)
+ cam_cx_ipeak_update_vote_cx_ipeak(soc_info, 0);
break;
+ }
}
return rc;
@@ -1214,6 +1282,9 @@ int cam_soc_util_get_dt_properties(struct cam_hw_soc_info *soc_info)
if (rc)
return rc;
+ if (of_find_property(of_node, "qcom,cam-cx-ipeak", NULL))
+ rc = cam_cx_ipeak_register_cx_ipeak(soc_info);
+
return rc;
}
@@ -1322,7 +1393,8 @@ int cam_soc_util_regulator_enable(struct regulator *rgltr,
}
static int cam_soc_util_request_pinctrl(
- struct cam_hw_soc_info *soc_info) {
+ struct cam_hw_soc_info *soc_info)
+{
struct cam_soc_pinctrl_info *device_pctrl = &soc_info->pinctrl_info;
struct device *dev = soc_info->dev;
diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.h b/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.h
index 91cc50daea83..80faed3edae2 100644
--- a/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.h
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, 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
@@ -156,6 +156,7 @@ struct cam_soc_gpio_data {
* @clk: Array of associated clock resources
* @clk_rate: 2D array of clock rates representing clock rate
* values at different vote levels
+ * @prev_clk_level Last vote level
* @src_clk_idx: Source clock index that is rate-controllable
* @clk_level_valid: Indicates whether corresponding level is valid
* @gpio_data: Pointer to gpio info
@@ -163,6 +164,8 @@ struct cam_soc_gpio_data {
* @dentry: Debugfs entry
* @clk_level_override: Clk level set from debugfs
* @clk_control: Enable/disable clk rate control through debugfs
+ * @cam_cx_ipeak_enable cx-ipeak enable/disable flag
+ * @cam_cx_ipeak_bit cx-ipeak mask for driver
* @soc_private: Soc private data
*/
struct cam_hw_soc_info {
@@ -198,6 +201,7 @@ struct cam_hw_soc_info {
const char *clk_name[CAM_SOC_MAX_CLK];
struct clk *clk[CAM_SOC_MAX_CLK];
int32_t clk_rate[CAM_MAX_VOTE][CAM_SOC_MAX_CLK];
+ int32_t prev_clk_level;
int32_t src_clk_idx;
bool clk_level_valid[CAM_MAX_VOTE];
@@ -207,6 +211,8 @@ struct cam_hw_soc_info {
struct dentry *dentry;
uint32_t clk_level_override;
bool clk_control_enable;
+ bool cam_cx_ipeak_enable;
+ int32_t cam_cx_ipeak_bit;
void *soc_private;
};
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index eed2fa473014..225bd239d9c8 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -384,9 +384,10 @@ static int hfi_process_session_error(u32 device_id,
}
static int hfi_process_event_notify(u32 device_id,
- struct hfi_msg_event_notify_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_event_notify_packet *pkt = _pkt;
dprintk(VIDC_DBG, "Received: EVENT_NOTIFY\n");
if (pkt->size < sizeof(struct hfi_msg_event_notify_packet)) {
@@ -425,9 +426,10 @@ static int hfi_process_event_notify(u32 device_id,
}
static int hfi_process_sys_init_done(u32 device_id,
- struct hfi_msg_sys_init_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_init_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
enum vidc_status status = VIDC_ERR_NONE;
@@ -464,9 +466,10 @@ err_no_prop:
}
static int hfi_process_sys_rel_resource_done(u32 device_id,
- struct hfi_msg_sys_release_resource_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_release_resource_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
enum vidc_status status = VIDC_ERR_NONE;
u32 pkt_size;
@@ -1274,9 +1277,10 @@ static void hfi_process_sess_get_prop_buf_req(
}
static int hfi_process_session_prop_info(u32 device_id,
- struct hfi_msg_session_property_info_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_property_info_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
struct buffer_requirements buff_req = { { {0} } };
@@ -1315,9 +1319,10 @@ static int hfi_process_session_prop_info(u32 device_id,
}
static int hfi_process_session_init_done(u32 device_id,
- struct hfi_msg_sys_session_init_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_session_init_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
struct vidc_hal_session_init_done session_init_done = { {0} };
@@ -1342,9 +1347,10 @@ static int hfi_process_session_init_done(u32 device_id,
}
static int hfi_process_session_load_res_done(u32 device_id,
- struct hfi_msg_session_load_resources_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_load_resources_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_LOAD_RESOURCES_DONE[%#x]\n",
@@ -1370,9 +1376,10 @@ static int hfi_process_session_load_res_done(u32 device_id,
}
static int hfi_process_session_flush_done(u32 device_id,
- struct hfi_msg_session_flush_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_flush_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_FLUSH_DONE[%#x]\n",
@@ -1413,9 +1420,10 @@ static int hfi_process_session_flush_done(u32 device_id,
}
static int hfi_process_session_etb_done(u32 device_id,
- struct hfi_msg_session_empty_buffer_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_empty_buffer_done_packet *pkt = _pkt;
struct msm_vidc_cb_data_done data_done = {0};
struct hfi_picture_type *hfi_picture_type = NULL;
@@ -1467,9 +1475,10 @@ static int hfi_process_session_etb_done(u32 device_id,
}
static int hfi_process_session_ftb_done(
- u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr,
+ u32 device_id, void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct vidc_hal_msg_pkt_hdr *msg_hdr = _pkt;
struct msm_vidc_cb_data_done data_done = {0};
bool is_decoder = false, is_encoder = false;
@@ -1595,9 +1604,10 @@ static int hfi_process_session_ftb_done(
}
static int hfi_process_session_start_done(u32 device_id,
- struct hfi_msg_session_start_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_start_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_START_DONE[%#x]\n",
@@ -1621,9 +1631,10 @@ static int hfi_process_session_start_done(u32 device_id,
}
static int hfi_process_session_stop_done(u32 device_id,
- struct hfi_msg_session_stop_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_stop_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_STOP_DONE[%#x]\n",
@@ -1648,9 +1659,10 @@ static int hfi_process_session_stop_done(u32 device_id,
}
static int hfi_process_session_rel_res_done(u32 device_id,
- struct hfi_msg_session_release_resources_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_release_resources_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_RELEASE_RESOURCES_DONE[%#x]\n",
@@ -1675,9 +1687,10 @@ static int hfi_process_session_rel_res_done(u32 device_id,
}
static int hfi_process_session_rel_buf_done(u32 device_id,
- struct hfi_msg_session_release_buffers_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_release_buffers_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
if (!pkt || pkt->size <
@@ -1708,9 +1721,10 @@ static int hfi_process_session_rel_buf_done(u32 device_id,
}
static int hfi_process_session_end_done(u32 device_id,
- struct hfi_msg_sys_session_end_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_session_end_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_END_DONE[%#x]\n", pkt->session_id);
@@ -1733,9 +1747,10 @@ static int hfi_process_session_end_done(u32 device_id,
}
static int hfi_process_session_abort_done(u32 device_id,
- struct hfi_msg_sys_session_abort_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_session_abort_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_ABORT_DONE[%#x]\n",
@@ -1803,9 +1818,10 @@ static void hfi_process_sys_get_prop_image_version(
}
static int hfi_process_sys_property_info(u32 device_id,
- struct hfi_msg_sys_property_info_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_property_info_packet *pkt = _pkt;
if (!pkt) {
dprintk(VIDC_ERR, "%s: invalid param\n", __func__);
return -EINVAL;
@@ -1837,7 +1853,7 @@ static int hfi_process_sys_property_info(u32 device_id,
}
static int hfi_process_ignore(u32 device_id,
- struct vidc_hal_msg_pkt_hdr *msg_hdr,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
*info = (struct msm_vidc_cb_info) {
@@ -1918,5 +1934,6 @@ int hfi_process_msg_packet(u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr,
break;
}
- return pkt_func ? pkt_func(device_id, msg_hdr, info) : -ENOTSUPP;
+ return pkt_func ?
+ pkt_func(device_id, (void *)msg_hdr, info) : -ENOTSUPP;
}
diff --git a/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c b/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
index 8eaf1fd192af..9f85f5d8b0f0 100644
--- a/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
@@ -322,9 +322,10 @@ static int hfi_process_session_error(u32 device_id,
}
static int hfi_process_event_notify(u32 device_id,
- struct hfi_msg_event_notify_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_event_notify_packet *pkt = _pkt;
dprintk(VIDC_DBG, "Received: EVENT_NOTIFY\n");
if (pkt->size < sizeof(struct hfi_msg_event_notify_packet)) {
@@ -363,9 +364,10 @@ static int hfi_process_event_notify(u32 device_id,
}
static int hfi_process_sys_init_done(u32 device_id,
- struct hfi_msg_sys_init_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_init_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
enum vidc_status status = VIDC_ERR_NONE;
@@ -402,9 +404,10 @@ err_no_prop:
}
static int hfi_process_sys_rel_resource_done(u32 device_id,
- struct hfi_msg_sys_release_resource_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_release_resource_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
enum vidc_status status = VIDC_ERR_NONE;
u32 pkt_size;
@@ -1228,9 +1231,10 @@ static void hfi_process_sess_get_prop_buf_req(
}
static int hfi_process_session_prop_info(u32 device_id,
- struct hfi_msg_session_property_info_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_property_info_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
struct hfi_profile_level profile_level = {0};
enum hal_h264_entropy entropy = HAL_UNUSED_ENTROPY;
@@ -1303,9 +1307,10 @@ static int hfi_process_session_prop_info(u32 device_id,
}
static int hfi_process_session_init_done(u32 device_id,
- struct hfi_msg_sys_session_init_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_session_init_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
struct vidc_hal_session_init_done session_init_done = { {0} };
@@ -1337,9 +1342,10 @@ static int hfi_process_session_init_done(u32 device_id,
}
static int hfi_process_session_load_res_done(u32 device_id,
- struct hfi_msg_session_load_resources_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_load_resources_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_LOAD_RESOURCES_DONE[%#x]\n",
@@ -1367,9 +1373,10 @@ static int hfi_process_session_load_res_done(u32 device_id,
}
static int hfi_process_session_flush_done(u32 device_id,
- struct hfi_msg_session_flush_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_flush_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_FLUSH_DONE[%#x]\n",
@@ -1412,9 +1419,10 @@ static int hfi_process_session_flush_done(u32 device_id,
}
static int hfi_process_session_etb_done(u32 device_id,
- struct hfi_msg_session_empty_buffer_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_empty_buffer_done_packet *pkt = _pkt;
struct msm_vidc_cb_data_done data_done = {0};
struct hfi_picture_type *hfi_picture_type = NULL;
@@ -1463,9 +1471,10 @@ static int hfi_process_session_etb_done(u32 device_id,
}
static int hfi_process_session_ftb_done(
- u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr,
+ u32 device_id, void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct vidc_hal_msg_pkt_hdr *msg_hdr = _pkt;
struct msm_vidc_cb_data_done data_done = {0};
bool is_decoder = false, is_encoder = false;
@@ -1590,9 +1599,10 @@ static int hfi_process_session_ftb_done(
}
static int hfi_process_session_start_done(u32 device_id,
- struct hfi_msg_session_start_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_start_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_START_DONE[%#x]\n",
@@ -1618,9 +1628,10 @@ static int hfi_process_session_start_done(u32 device_id,
}
static int hfi_process_session_stop_done(u32 device_id,
- struct hfi_msg_session_stop_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_stop_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_STOP_DONE[%#x]\n",
@@ -1647,9 +1658,10 @@ static int hfi_process_session_stop_done(u32 device_id,
}
static int hfi_process_session_rel_res_done(u32 device_id,
- struct hfi_msg_session_release_resources_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_release_resources_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_RELEASE_RESOURCES_DONE[%#x]\n",
@@ -1676,9 +1688,10 @@ static int hfi_process_session_rel_res_done(u32 device_id,
}
static int hfi_process_session_rel_buf_done(u32 device_id,
- struct hfi_msg_session_release_buffers_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_release_buffers_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
if (!pkt || pkt->size <
@@ -1711,9 +1724,10 @@ static int hfi_process_session_rel_buf_done(u32 device_id,
}
static int hfi_process_session_end_done(u32 device_id,
- struct hfi_msg_sys_session_end_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_session_end_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_END_DONE[%#x]\n", pkt->session_id);
@@ -1738,9 +1752,10 @@ static int hfi_process_session_end_done(u32 device_id,
}
static int hfi_process_session_abort_done(u32 device_id,
- struct hfi_msg_sys_session_abort_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_session_abort_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_ABORT_DONE[%#x]\n",
@@ -1846,9 +1861,10 @@ static void hfi_process_sys_get_prop_image_version(
}
static int hfi_process_sys_property_info(u32 device_id,
- struct hfi_msg_sys_property_info_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_property_info_packet *pkt = _pkt;
if (!pkt) {
dprintk(VIDC_ERR, "%s: invalid param\n", __func__);
return -EINVAL;
@@ -1880,7 +1896,7 @@ static int hfi_process_sys_property_info(u32 device_id,
}
static int hfi_process_ignore(u32 device_id,
- struct vidc_hal_msg_pkt_hdr *msg_hdr,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
*info = (struct msm_vidc_cb_info) {
@@ -1964,5 +1980,6 @@ int hfi_process_msg_packet(u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr,
break;
}
- return pkt_func ? pkt_func(device_id, msg_hdr, info) : -ENOTSUPP;
+ return pkt_func ?
+ pkt_func(device_id, (void *)msg_hdr, info) : -ENOTSUPP;
}
diff --git a/drivers/media/platform/msm/vidc_3x/msm_vidc.c b/drivers/media/platform/msm/vidc_3x/msm_vidc.c
index 983e600c6480..0a2d380dbbd7 100644
--- a/drivers/media/platform/msm/vidc_3x/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc_3x/msm_vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, 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
@@ -1278,13 +1278,12 @@ void *msm_vidc_open(int core_id, int session_type)
return inst;
fail_init:
+ mutex_lock(&core->lock);
v4l2_fh_del(&inst->event_handler);
v4l2_fh_exit(&inst->event_handler);
- vb2_queue_release(&inst->bufq[OUTPUT_PORT].vb2_bufq);
-
- mutex_lock(&core->lock);
list_del(&inst->list);
mutex_unlock(&core->lock);
+ vb2_queue_release(&inst->bufq[OUTPUT_PORT].vb2_bufq);
fail_bufq_output:
vb2_queue_release(&inst->bufq[CAPTURE_PORT].vb2_bufq);
diff --git a/drivers/media/platform/msm/vidc_3x/msm_vidc_common.c b/drivers/media/platform/msm/vidc_3x/msm_vidc_common.c
index 22f49ce02e47..af2514c60065 100644
--- a/drivers/media/platform/msm/vidc_3x/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc_3x/msm_vidc_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, 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
@@ -1638,11 +1638,11 @@ static void msm_comm_clean_notify_client(struct msm_vidc_core *core)
list_for_each_entry(inst, &core->instances, list) {
mutex_lock(&inst->lock);
inst->state = MSM_VIDC_CORE_INVALID;
- mutex_unlock(&inst->lock);
dprintk(VIDC_WARN,
"%s Send sys error for inst %pK\n", __func__, inst);
msm_vidc_queue_v4l2_event(inst,
V4L2_EVENT_MSM_VIDC_SYS_ERROR);
+ mutex_unlock(&inst->lock);
}
mutex_unlock(&core->lock);
}
diff --git a/drivers/misc/hdcp_qseecom.c b/drivers/misc/hdcp_qseecom.c
index 6ce377667623..13175d041833 100644
--- a/drivers/misc/hdcp_qseecom.c
+++ b/drivers/misc/hdcp_qseecom.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, 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
@@ -2037,6 +2037,30 @@ bool hdcp1_check_if_supported_load_app(void)
return hdcp1_supported;
}
+void hdcp1_unload_app(void)
+{
+ int rc = 0;
+
+ if (!hdcp1_supported) {
+ pr_debug("hdcp1 is not supported\n");
+ return;
+ }
+
+ if (!hdcp1_handle) {
+ pr_debug("invalid hdcp1 handle\n");
+ return;
+ }
+
+ rc = qseecom_shutdown_app(&hdcp1_handle);
+ if (rc) {
+ pr_debug("qseecom_shutdown_app failed with ERR = %d\n", rc);
+ return;
+ }
+
+ hdcp1_handle = NULL;
+ pr_debug("hdcp1 app unloaded\n");
+}
+
/* APIs exposed to all clients */
int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb)
{
diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c
index 87fc883e8a73..a4d35d94de0c 100644
--- a/drivers/mmc/host/cmdq_hci.c
+++ b/drivers/mmc/host/cmdq_hci.c
@@ -911,11 +911,13 @@ static void cmdq_finish_data(struct mmc_host *mmc, unsigned int tag)
cmdq_runtime_pm_put(cq_host);
- if (cq_host->ops->crypto_cfg_end) {
- err = cq_host->ops->crypto_cfg_end(mmc, mrq);
- if (err) {
- pr_err("%s: failed to end ice config: err %d tag %d\n",
- mmc_hostname(mmc), err, tag);
+ if (!(mrq->cmdq_req->cmdq_req_flags & DCMD)) {
+ if (cq_host->ops->crypto_cfg_end) {
+ err = cq_host->ops->crypto_cfg_end(mmc, mrq);
+ if (err) {
+ pr_err("%s: failed to end ice config: err %d tag %d\n",
+ mmc_hostname(mmc), err, tag);
+ }
}
}
if (!(cq_host->caps & CMDQ_CAP_CRYPTO_SUPPORT) &&
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 37df1bf277ca..09e8d38f57ae 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -752,11 +752,7 @@ static void cpu_pm_pmu_setup(struct arm_pmu *armpmu, unsigned long cmd)
if (!event)
continue;
- /*
- * Check if an attempt was made to free this event during
- * the CPU went offline.
- */
- if (event->state == PERF_EVENT_STATE_ZOMBIE)
+ if (event->state != PERF_EVENT_STATE_ACTIVE)
continue;
switch (cmd) {
@@ -882,10 +878,8 @@ static int arm_perf_starting_cpu(unsigned int cpu, struct hlist_node *node)
if (!pmu || !cpumask_test_cpu(cpu, &pmu->supported_cpus))
return 0;
- data.cmd = CPU_PM_EXIT;
- cpu_pm_pmu_common(&data);
- if (data.ret == NOTIFY_DONE)
- return 0;
+ if (pmu->reset)
+ pmu->reset(pmu);
if (data.armpmu->pmu_state != ARM_PMU_STATE_OFF &&
data.armpmu->plat_device) {
@@ -911,8 +905,6 @@ static int arm_perf_stopping_cpu(unsigned int cpu, struct hlist_node *node)
if (!pmu || !cpumask_test_cpu(cpu, &pmu->supported_cpus))
return 0;
- data.cmd = CPU_PM_ENTER;
- cpu_pm_pmu_common(&data);
/* Disarm the PMU IRQ before disappearing. */
if (data.armpmu->pmu_state == ARM_PMU_STATE_RUNNING &&
data.armpmu->plat_device) {
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
index f1f6b900d474..b3c38b9d7f86 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, 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
@@ -737,8 +737,14 @@ ssize_t ipa_read(struct file *filp, char __user *buf, size_t count,
IPADBG("msg=%pK\n", msg);
locked = 0;
mutex_unlock(&ipa_ctx->msg_lock);
+ if (count < sizeof(struct ipa_msg_meta)) {
+ kfree(msg);
+ msg = NULL;
+ ret = -EFAULT;
+ break;
+ }
if (copy_to_user(buf, &msg->meta,
- sizeof(struct ipa_msg_meta))) {
+ sizeof(struct ipa_msg_meta))) {
kfree(msg);
msg = NULL;
ret = -EFAULT;
@@ -747,8 +753,15 @@ ssize_t ipa_read(struct file *filp, char __user *buf, size_t count,
buf += sizeof(struct ipa_msg_meta);
count -= sizeof(struct ipa_msg_meta);
if (msg->buff) {
- if (copy_to_user(buf, msg->buff,
- msg->meta.msg_len)) {
+ if (count >= msg->meta.msg_len) {
+ if (copy_to_user(buf, msg->buff,
+ msg->meta.msg_len)) {
+ kfree(msg);
+ msg = NULL;
+ ret = -EFAULT;
+ break;
+ }
+ } else {
kfree(msg);
msg = NULL;
ret = -EFAULT;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
index c348e26b6b69..d41cdb7c2f90 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, 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
@@ -745,6 +745,12 @@ ssize_t ipa3_read(struct file *filp, char __user *buf, size_t count,
if (msg) {
locked = 0;
mutex_unlock(&ipa3_ctx->msg_lock);
+ if (count < sizeof(struct ipa_msg_meta)) {
+ kfree(msg);
+ msg = NULL;
+ ret = -EFAULT;
+ break;
+ }
if (copy_to_user(buf, &msg->meta,
sizeof(struct ipa_msg_meta))) {
ret = -EFAULT;
@@ -755,8 +761,15 @@ ssize_t ipa3_read(struct file *filp, char __user *buf, size_t count,
buf += sizeof(struct ipa_msg_meta);
count -= sizeof(struct ipa_msg_meta);
if (msg->buff) {
- if (copy_to_user(buf, msg->buff,
- msg->meta.msg_len)) {
+ if (count >= msg->meta.msg_len) {
+ if (copy_to_user(buf, msg->buff,
+ msg->meta.msg_len)) {
+ ret = -EFAULT;
+ kfree(msg);
+ msg = NULL;
+ break;
+ }
+ } else {
ret = -EFAULT;
kfree(msg);
msg = NULL;
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index bc1855ea5d48..f56b9837f259 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019 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
@@ -1115,10 +1115,14 @@ static int smb2_batt_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_CHARGE_FULL:
case POWER_SUPPLY_PROP_CYCLE_COUNT:
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- case POWER_SUPPLY_PROP_CURRENT_NOW:
case POWER_SUPPLY_PROP_TEMP:
rc = smblib_get_prop_from_bms(chg, psp, val);
break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ rc = smblib_get_prop_from_bms(chg, psp, val);
+ if (!rc)
+ val->intval *= (-1);
+ break;
case POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE:
val->intval = chg->fcc_stepper_enable;
break;
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index 7994741ccb1c..a4410734f6c5 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -1367,6 +1367,8 @@ static int smb5_batt_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_CURRENT_NOW:
rc = smblib_get_prop_from_bms(chg,
POWER_SUPPLY_PROP_CURRENT_NOW, val);
+ if (!rc)
+ val->intval *= (-1);
break;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
val->intval = get_client_vote(chg->fcc_votable,
diff --git a/drivers/power/supply/qcom/qpnp-smbcharger.c b/drivers/power/supply/qcom/qpnp-smbcharger.c
index 896509dac561..523fe47a4d54 100644
--- a/drivers/power/supply/qcom/qpnp-smbcharger.c
+++ b/drivers/power/supply/qcom/qpnp-smbcharger.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 2018-2019, 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
@@ -308,6 +308,7 @@ enum pmic_subtype {
PMI8950 = 17,
PMI8996 = 19,
PMI8937 = 55,
+ PMI8940 = 64,
};
enum smbchg_wa {
@@ -1133,6 +1134,28 @@ static int get_prop_batt_voltage_max_design(struct smbchg_chip *chip)
return uv;
}
+static int get_prop_batt_charge_counter(struct smbchg_chip *chip)
+{
+ int bcc = 0, rc;
+
+ rc = get_property_from_fg(chip,
+ POWER_SUPPLY_PROP_CHARGE_COUNTER, &bcc);
+ if (rc)
+ pr_smb(PR_STATUS, "Couldn't get charge_counter rc = %d\n", rc);
+ return bcc;
+}
+
+static int get_prop_batt_cycle_count(struct smbchg_chip *chip)
+{
+ int bcc = 0, rc;
+
+ rc = get_property_from_fg(chip,
+ POWER_SUPPLY_PROP_CYCLE_COUNT, &bcc);
+ if (rc)
+ pr_smb(PR_STATUS, "Couldn't get cycle_count rc = %d\n", rc);
+ return bcc;
+}
+
static int get_prop_batt_health(struct smbchg_chip *chip)
{
if (chip->batt_hot)
@@ -5899,6 +5922,8 @@ static enum power_supply_property smbchg_battery_properties[] = {
POWER_SUPPLY_PROP_RESTRICTED_CHARGING,
POWER_SUPPLY_PROP_ALLOW_HVDCP3,
POWER_SUPPLY_PROP_MAX_PULSE_ALLOWED,
+ POWER_SUPPLY_PROP_CHARGE_COUNTER,
+ POWER_SUPPLY_PROP_CYCLE_COUNT,
};
static int smbchg_battery_set_property(struct power_supply *psy,
@@ -6118,6 +6143,12 @@ static int smbchg_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_MAX_PULSE_ALLOWED:
val->intval = chip->max_pulse_allowed;
break;
+ case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+ val->intval = get_prop_batt_charge_counter(chip);
+ break;
+ case POWER_SUPPLY_PROP_CYCLE_COUNT:
+ val->intval = get_prop_batt_cycle_count(chip);
+ break;
default:
return -EINVAL;
}
@@ -8096,6 +8127,8 @@ static int smbchg_check_chg_version(struct smbchg_chip *chip)
case PMI8950:
chip->wa_flags |= SMBCHG_RESTART_WA;
case PMI8937:
+ /* fall through */
+ case PMI8940:
chip->wa_flags |= SMBCHG_BATT_OV_WA;
if (pmic_rev_id->rev4 < 2) /* PMI8950 1.0 */ {
chip->wa_flags |= SMBCHG_AICL_DEGLITCH_WA;
@@ -8110,7 +8143,9 @@ static int smbchg_check_chg_version(struct smbchg_chip *chip)
ARRAY_SIZE(aicl_rerun_period_schg_lite);
chip->schg_version = QPNP_SCHG_LITE;
- if (pmic_rev_id->pmic_subtype == PMI8937)
+ /* PMI8937/PMI8940 doesn't support HVDCP */
+ if ((pmic_rev_id->pmic_subtype == PMI8937)
+ || (pmic_rev_id->pmic_subtype == PMI8940))
chip->hvdcp_not_supported = true;
break;
case PMI8996:
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index e23f13e2236f..9b0ec47df85a 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -2888,6 +2888,7 @@ static int __smblib_set_prop_pd_active(struct smb_charger *chg, bool pd_active)
chg->pd_active = pd_active;
if (chg->pd_active) {
+ chg->real_charger_type = POWER_SUPPLY_TYPE_USB_PD;
vote(chg->apsd_disable_votable, PD_VOTER, true, 0);
vote(chg->pd_allowed_votable, PD_VOTER, true, 0);
vote(chg->usb_irq_enable_votable, PD_VOTER, true, 0);
diff --git a/drivers/power/supply/qcom/smb1360-charger-fg.c b/drivers/power/supply/qcom/smb1360-charger-fg.c
index 4e98ec752fa7..41dcf1dca25d 100644
--- a/drivers/power/supply/qcom/smb1360-charger-fg.c
+++ b/drivers/power/supply/qcom/smb1360-charger-fg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -31,6 +31,7 @@
#include <linux/qpnp/qpnp-adc.h>
#include <linux/completion.h>
#include <linux/pm_wakeup.h>
+#include <linux/of_irq.h>
#define _SMB1360_MASK(BITS, POS) \
((unsigned char)(((1 << (BITS)) - 1) << (POS)))
@@ -405,6 +406,7 @@ struct smb1360_chip {
bool otg_fet_present;
bool fet_gain_enabled;
int otg_fet_enable_gpio;
+ int usb_id_gpio;
/* status tracking */
int voltage_now;
@@ -466,6 +468,7 @@ struct smb1360_chip {
int cold_hysteresis;
int hot_hysteresis;
struct extcon_dev *extcon;
+ int usb_id_irq;
};
static int chg_time[] = {
@@ -2885,6 +2888,28 @@ static irqreturn_t smb1360_stat_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static irqreturn_t smb1360_usb_id_irq_handler(int irq, void *dev_id)
+{
+ struct smb1360_chip *chip = dev_id;
+ int rc = 0;
+ bool id_state;
+
+ id_state = gpio_get_value(chip->usb_id_gpio);
+
+ rc = smb1360_masked_write(chip, CMD_CHG_REG, CMD_OTG_EN_BIT,
+ !id_state ? CMD_OTG_EN_BIT : 0);
+ if (rc) {
+ pr_err("Couldn't enable OTG mode rc=%d\n", rc);
+ return IRQ_HANDLED;
+ }
+ extcon_set_state_sync(chip->extcon, EXTCON_USB_HOST,
+ !id_state ? true : false);
+
+ pr_debug("usb_id_irq triggered, id_state = %d\n", id_state);
+
+ return IRQ_HANDLED;
+}
+
static int show_irq_count(struct seq_file *m, void *data)
{
int i, j, total = 0;
@@ -3421,6 +3446,10 @@ static int smb1360_regulator_init(struct smb1360_chip *chip)
int rc = 0;
struct regulator_config cfg = {};
+ /* OTG is enabled by SMB1360 if usb-id config is defined */
+ if (chip->usb_id_gpio > 0 && chip->usb_id_irq > 0)
+ return 0;
+
chip->otg_vreg.rdesc.owner = THIS_MODULE;
chip->otg_vreg.rdesc.type = REGULATOR_VOLTAGE;
chip->otg_vreg.rdesc.ops = &smb1360_otg_reg_ops;
@@ -3557,6 +3586,7 @@ static int determine_initial_status(struct smb1360_chip *chip)
{
int rc;
u8 reg = 0;
+ bool id_state;
/*
* It is okay to read the IRQ status as the irq's are
@@ -3621,6 +3651,25 @@ static int determine_initial_status(struct smb1360_chip *chip)
else
extcon_set_cable_state_(chip->extcon, EXTCON_USB, true);
+ pr_debug("usb %s at boot\n", chip->usb_present ? "present" : "absent");
+
+ /*check otg presence and notify*/
+ if (chip->usb_id_gpio != -EINVAL) {
+ id_state = gpio_get_value(chip->usb_id_gpio);
+ /* usb-id is low, enable OTG */
+ if (!id_state) {
+ rc = smb1360_masked_write(chip, CMD_CHG_REG,
+ CMD_OTG_EN_BIT, CMD_OTG_EN_BIT);
+ if (rc) {
+ pr_err("Couldn't enable OTG mode rc=%d\n", rc);
+ return rc;
+ }
+ extcon_set_state_sync(chip->extcon, EXTCON_USB_HOST,
+ true);
+ pr_debug("OTG enabled at boot\n");
+ }
+ }
+
power_supply_changed(chip->usb_psy);
return 0;
}
@@ -4752,6 +4801,11 @@ static int smb_parse_dt(struct smb1360_chip *chip)
return rc;
}
}
+ chip->usb_id_gpio = -EINVAL;
+ if (of_find_property(node, "qcom,usb-id-gpio", NULL)) {
+ chip->usb_id_gpio = of_get_named_gpio(node,
+ "qcom,usb-id-gpio", 0);
+ }
chip->pulsed_irq = of_property_read_bool(node, "qcom,stat-pulsed-irq");
@@ -5073,6 +5127,28 @@ static int smb1360_probe(struct i2c_client *client,
enable_irq_wake(client->irq);
}
+ chip->usb_id_irq = of_irq_get_byname(chip->dev->of_node,
+ "smb1360_usb_id_irq");
+ if (chip->usb_id_irq > 0) {
+ if (chip->usb_id_gpio == -EINVAL) {
+ pr_err("usb-id gpio not defined\n");
+ } else {
+ rc = devm_request_threaded_irq(&client->dev,
+ chip->usb_id_irq, NULL,
+ smb1360_usb_id_irq_handler,
+ IRQF_ONESHOT
+ | IRQF_TRIGGER_FALLING
+ | IRQF_TRIGGER_RISING,
+ "smb1360_usb_id_irq", chip);
+ if (rc < 0) {
+ dev_err(&client->dev,
+ "usb-id request_irq for irq=%d failed rc = %d\n",
+ chip->usb_id_irq, rc);
+ goto unregister_batt_psy;
+ }
+ enable_irq_wake(chip->usb_id_irq);
+ }
+ }
chip->debug_root = debugfs_create_dir("smb1360", NULL);
if (!chip->debug_root)
dev_err(chip->dev, "Couldn't create debug dir\n");
@@ -5201,7 +5277,8 @@ static int smb1360_probe(struct i2c_client *client,
unregister_batt_psy:
power_supply_unregister(chip->batt_psy);
fail_hw_init:
- regulator_unregister(chip->otg_vreg.rdev);
+ if (chip->otg_vreg.rdev)
+ regulator_unregister(chip->otg_vreg.rdev);
destroy_mutex:
power_supply_unregister(chip->usb_psy);
wakeup_source_trash(&chip->smb1360_ws.source);
@@ -5218,8 +5295,9 @@ destroy_mutex:
static int smb1360_remove(struct i2c_client *client)
{
struct smb1360_chip *chip = i2c_get_clientdata(client);
+ if (chip->otg_vreg.rdev)
+ regulator_unregister(chip->otg_vreg.rdev);
- regulator_unregister(chip->otg_vreg.rdev);
power_supply_unregister(chip->usb_psy);
power_supply_unregister(chip->batt_psy);
wakeup_source_trash(&chip->smb1360_ws.source);
diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c
index d4fe6eede3b4..a2b725706667 100644
--- a/drivers/scsi/ufs/ufs-qcom-ice.c
+++ b/drivers/scsi/ufs/ufs-qcom-ice.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, 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
@@ -226,14 +226,17 @@ int ufs_qcom_ice_init(struct ufs_qcom_host *qcom_host)
}
qcom_host->dbg_print_en |= UFS_QCOM_ICE_DEFAULT_DBG_PRINT_EN;
- ice_workqueue = alloc_workqueue("ice-set-key",
- WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
if (!ice_workqueue) {
- dev_err(ufs_dev, "%s: workqueue allocation failed.\n",
+ ice_workqueue = alloc_workqueue("ice-set-key",
+ WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
+ if (!ice_workqueue) {
+ dev_err(ufs_dev, "%s: workqueue allocation failed.\n",
__func__);
- goto out;
+ err = -ENOMEM;
+ goto out;
+ }
+ INIT_WORK(&qcom_host->ice_cfg_work, ufs_qcom_ice_cfg_work);
}
- INIT_WORK(&qcom_host->ice_cfg_work, ufs_qcom_ice_cfg_work);
out:
return err;
@@ -286,6 +289,17 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host,
* propagate so it will be re-queued.
*/
if (err == -EAGAIN) {
+ if (!ice_workqueue) {
+ spin_unlock_irqrestore(
+ &qcom_host->ice_work_lock,
+ flags);
+
+ dev_err(qcom_host->hba->dev,
+ "%s: error %d workqueue NULL\n",
+ __func__, err);
+ return -EINVAL;
+ }
+
dev_dbg(qcom_host->hba->dev,
"%s: scheduling task for ice setup\n",
__func__);
@@ -405,6 +419,16 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
* propagate so it will be re-queued.
*/
if (err == -EAGAIN) {
+ if (!ice_workqueue) {
+ spin_unlock_irqrestore(
+ &qcom_host->ice_work_lock,
+ flags);
+
+ dev_err(qcom_host->hba->dev,
+ "%s: error %d workqueue NULL\n",
+ __func__, err);
+ return -EINVAL;
+ }
dev_dbg(qcom_host->hba->dev,
"%s: scheduling task for ice setup\n",
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index d70fc6bb9d72..3ae576655f8b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3445,18 +3445,6 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
int tag;
struct completion wait;
unsigned long flags;
- bool has_read_lock = false;
-
- /*
- * May get invoked from shutdown and IOCTL contexts.
- * In shutdown context, it comes in with lock acquired.
- * In error recovery context, it may come with lock acquired.
- */
-
- if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) {
- down_read(&hba->lock);
- has_read_lock = true;
- }
/*
* Get free slot, sleep if slots are unavailable.
@@ -3489,8 +3477,6 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
out_put_tag:
ufshcd_put_dev_cmd_tag(hba, tag);
wake_up(&hba->dev_cmd.tag_wq);
- if (has_read_lock)
- up_read(&hba->lock);
return err;
}
@@ -3565,10 +3551,15 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
struct ufs_query_res *response = NULL;
int err, index = 0, selector = 0;
int timeout = QUERY_REQ_TIMEOUT;
+ bool has_read_lock = false;
BUG_ON(!hba);
ufshcd_hold_all(hba);
+ if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) {
+ down_read(&hba->lock);
+ has_read_lock = true;
+ }
mutex_lock(&hba->dev_cmd.lock);
ufshcd_init_query(hba, &request, &response, opcode, idn, index,
selector);
@@ -3612,6 +3603,8 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
out_unlock:
mutex_unlock(&hba->dev_cmd.lock);
+ if (has_read_lock)
+ up_read(&hba->lock);
ufshcd_release_all(hba);
return err;
}
@@ -3634,6 +3627,7 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
struct ufs_query_req *request = NULL;
struct ufs_query_res *response = NULL;
int err;
+ bool has_read_lock = false;
BUG_ON(!hba);
@@ -3645,6 +3639,16 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
goto out;
}
+ /*
+ * May get invoked from shutdown and IOCTL contexts.
+ * In shutdown context, it comes in with lock acquired.
+ * In error recovery context, it may come with lock acquired.
+ */
+
+ if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) {
+ down_read(&hba->lock);
+ has_read_lock = true;
+ }
mutex_lock(&hba->dev_cmd.lock);
ufshcd_init_query(hba, &request, &response, opcode, idn, index,
selector);
@@ -3677,6 +3681,8 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
out_unlock:
mutex_unlock(&hba->dev_cmd.lock);
+ if (has_read_lock)
+ up_read(&hba->lock);
out:
ufshcd_release_all(hba);
return err;
@@ -3727,6 +3733,7 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
struct ufs_query_req *request = NULL;
struct ufs_query_res *response = NULL;
int err;
+ bool has_read_lock = false;
BUG_ON(!hba);
@@ -3745,6 +3752,10 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
goto out;
}
+ if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) {
+ down_read(&hba->lock);
+ has_read_lock = true;
+ }
mutex_lock(&hba->dev_cmd.lock);
ufshcd_init_query(hba, &request, &response, opcode, idn, index,
selector);
@@ -3780,6 +3791,9 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
out_unlock:
mutex_unlock(&hba->dev_cmd.lock);
+ if (has_read_lock)
+ up_read(&hba->lock);
+
out:
ufshcd_release_all(hba);
return err;
@@ -5301,8 +5315,13 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba)
{
int err = 0;
int retries;
+ bool has_read_lock = false;
ufshcd_hold_all(hba);
+ if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) {
+ down_read(&hba->lock);
+ has_read_lock = true;
+ }
mutex_lock(&hba->dev_cmd.lock);
for (retries = NOP_OUT_RETRIES; retries > 0; retries--) {
err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_NOP,
@@ -5314,6 +5333,8 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba)
dev_dbg(hba->dev, "%s: error %d retrying\n", __func__, err);
}
mutex_unlock(&hba->dev_cmd.lock);
+ if (has_read_lock)
+ up_read(&hba->lock);
ufshcd_release_all(hba);
if (err)
@@ -10252,12 +10273,9 @@ static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up)
* e.g. link_recovery. Hence, release the rw_sem
* before hibern8.
*/
- up_write(&hba->lock);
ret = ufshcd_uic_hibern8_enter(hba);
- down_write(&hba->lock);
if (ret)
- /* link will be bad state so no need to scale_up_gear */
- return ret;
+ goto scale_up_gear;
ufshcd_custom_cmd_log(hba, "Hibern8-entered");
}
@@ -10269,8 +10287,7 @@ static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up)
if (ufshcd_is_auto_hibern8_supported(hba)) {
ret = ufshcd_uic_hibern8_exit(hba);
if (ret)
- /* link will be bad state so no need to scale_up_gear */
- return ret;
+ goto scale_up_gear;
ufshcd_custom_cmd_log(hba, "Hibern8-Exited");
}
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 34be2301be20..44f34cf4227e 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -2083,7 +2083,7 @@ static int ngd_slim_runtime_suspend(struct device *device)
#ifdef CONFIG_PM_SLEEP
static int ngd_slim_suspend(struct device *dev)
{
- int ret = -EBUSY;
+ int ret = 0;
struct platform_device *pdev = to_platform_device(dev);
struct msm_slim_ctrl *cdev;
@@ -2092,6 +2092,13 @@ static int ngd_slim_suspend(struct device *dev)
return 0;
cdev = platform_get_drvdata(pdev);
+
+ if (cdev->state == MSM_CTRL_AWAKE) {
+ ret = -EBUSY;
+ SLIM_INFO(cdev, "system suspend: %d\n", ret);
+ return ret;
+
+ }
if (!pm_runtime_enabled(dev) ||
(!pm_runtime_suspended(dev) &&
cdev->state == MSM_CTRL_IDLE)) {
@@ -2109,17 +2116,6 @@ static int ngd_slim_suspend(struct device *dev)
cdev->qmi.deferred_resp = false;
}
}
- if (ret == -EBUSY) {
- /*
- * There is a possibility that some audio stream is active
- * during suspend. We dont want to return suspend failure in
- * that case so that display and relevant components can still
- * go to suspend.
- * If there is some other error, then it should be passed-on
- * to system level suspend
- */
- ret = 0;
- }
SLIM_INFO(cdev, "system suspend\n");
return ret;
}
diff --git a/drivers/soc/qcom/glink_spi_xprt.c b/drivers/soc/qcom/glink_spi_xprt.c
index a08c4bfde4a2..efcd94cdda01 100644
--- a/drivers/soc/qcom/glink_spi_xprt.c
+++ b/drivers/soc/qcom/glink_spi_xprt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, 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
@@ -484,6 +484,13 @@ static int glink_spi_xprt_rx_cmd(struct edge_info *einfo, void *dst,
int ret;
read_id = einfo->rx_fifo_read;
+ if ((read_id > (einfo->rx_fifo_start + einfo->fifo_size)) ||
+ (read_id < einfo->rx_fifo_start)) {
+ pr_err("%s: Invalid rx_fifo_read: %d, start: %d, size: %d\n",
+ __func__, read_id, einfo->rx_fifo_start,
+ einfo->fifo_size);
+ return -EINVAL;
+ }
do {
if ((read_id + size_to_read) >=
(einfo->rx_fifo_start + einfo->fifo_size))
@@ -722,11 +729,11 @@ static void process_rx_cmd(struct edge_info *einfo,
struct rx_short_data_desc {
unsigned char data[SHORT_PKT_SIZE];
};
- struct command *cmd;
+ struct command *cmd = NULL;
struct intent_desc *intents;
struct rx_desc *rx_descp;
struct rx_short_data_desc *rx_sd_descp;
- int offset = 0;
+ uint64_t offset = 0;
int rcu_id;
uint16_t rcid;
uint16_t name_len;
@@ -742,6 +749,8 @@ static void process_rx_cmd(struct edge_info *einfo,
}
while (offset < rx_size) {
+ if (offset + sizeof(*cmd) > rx_size)
+ goto err;
cmd = (struct command *)(rx_data + offset);
offset += sizeof(*cmd);
switch (cmd->id) {
@@ -760,7 +769,12 @@ static void process_rx_cmd(struct edge_info *einfo,
case OPEN_CMD:
rcid = cmd->param1;
name_len = (uint16_t)(cmd->param2 & 0xFFFF);
+ if (name_len > GLINK_NAME_SIZE)
+ goto err;
prio = (uint16_t)((cmd->param2 & 0xFFFF0000) >> 16);
+ if (offset + ALIGN(name_len, FIFO_ALIGNMENT) >
+ rx_size)
+ goto err;
name = (char *)(rx_data + offset);
offset += ALIGN(name_len, FIFO_ALIGNMENT);
einfo->xprt_if.glink_core_if_ptr->rx_cmd_ch_remote_open(
@@ -786,6 +800,8 @@ static void process_rx_cmd(struct edge_info *einfo,
case RX_INTENT_CMD:
for (i = 0; i < cmd->param2; i++) {
+ if (offset + sizeof(*intents) > rx_size)
+ goto err;
intents = (struct intent_desc *)
(rx_data + offset);
offset += sizeof(*intents);
@@ -821,6 +837,8 @@ static void process_rx_cmd(struct edge_info *einfo,
case TX_DATA_CONT_CMD:
case TRACER_PKT_CMD:
case TRACER_PKT_CONT_CMD:
+ if (offset + sizeof(*rx_descp) > rx_size)
+ goto err;
rx_descp = (struct rx_desc *)(rx_data + offset);
offset += sizeof(*rx_descp);
process_rx_data(einfo, cmd->id, cmd->param1,
@@ -830,6 +848,8 @@ static void process_rx_cmd(struct edge_info *einfo,
break;
case TX_SHORT_DATA_CMD:
+ if (offset + sizeof(*rx_sd_descp) > rx_size)
+ goto err;
rx_sd_descp = (struct rx_short_data_desc *)
(rx_data + offset);
offset += sizeof(*rx_sd_descp);
@@ -858,6 +878,13 @@ static void process_rx_cmd(struct edge_info *einfo,
}
}
srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+err:
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ if (cmd)
+ pr_err("%s: invalid size of rx_data: %d, cmd : %d\n",
+ __func__, rx_size, cmd->id);
+ return;
}
/**
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 84ad1e74f73c..f3acd4113b06 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -76,6 +76,8 @@ module_param(qmi_timeout, ulong, 0600);
#define ICNSS_MAX_PROBE_CNT 2
+#define PROBE_TIMEOUT 5000
+
#define icnss_ipc_log_string(_x...) do { \
if (icnss_ipc_log_context) \
ipc_log_string(icnss_ipc_log_context, _x); \
@@ -286,6 +288,7 @@ enum icnss_driver_state {
ICNSS_DRIVER_UNLOADING,
ICNSS_REJUVENATE,
ICNSS_MODE_ON,
+ ICNSS_BLOCK_SHUTDOWN,
};
struct ce_irq_list {
@@ -475,6 +478,7 @@ static struct icnss_priv {
struct mutex dev_lock;
uint32_t fw_error_fatal_irq;
uint32_t fw_early_crash_irq;
+ struct completion unblock_shutdown;
} *penv;
#ifdef CONFIG_ICNSS_DEBUG
@@ -1164,6 +1168,21 @@ bool icnss_is_fw_ready(void)
}
EXPORT_SYMBOL(icnss_is_fw_ready);
+void icnss_block_shutdown(bool status)
+{
+ if (!penv)
+ return;
+
+ if (status) {
+ set_bit(ICNSS_BLOCK_SHUTDOWN, &penv->state);
+ reinit_completion(&penv->unblock_shutdown);
+ } else {
+ clear_bit(ICNSS_BLOCK_SHUTDOWN, &penv->state);
+ complete(&penv->unblock_shutdown);
+ }
+}
+EXPORT_SYMBOL(icnss_block_shutdown);
+
bool icnss_is_fw_down(void)
{
if (!penv)
@@ -2256,6 +2275,7 @@ static int icnss_call_driver_probe(struct icnss_priv *priv)
icnss_hw_power_on(priv);
+ icnss_block_shutdown(true);
while (probe_cnt < ICNSS_MAX_PROBE_CNT) {
ret = priv->ops->probe(&priv->pdev->dev);
probe_cnt++;
@@ -2265,9 +2285,11 @@ static int icnss_call_driver_probe(struct icnss_priv *priv)
if (ret < 0) {
icnss_pr_err("Driver probe failed: %d, state: 0x%lx, probe_cnt: %d\n",
ret, priv->state, probe_cnt);
+ icnss_block_shutdown(false);
goto out;
}
+ icnss_block_shutdown(false);
set_bit(ICNSS_DRIVER_PROBED, &priv->state);
return 0;
@@ -2406,6 +2428,7 @@ static int icnss_driver_event_register_driver(void *data)
if (ret)
goto out;
+ icnss_block_shutdown(true);
while (probe_cnt < ICNSS_MAX_PROBE_CNT) {
ret = penv->ops->probe(&penv->pdev->dev);
probe_cnt++;
@@ -2415,9 +2438,11 @@ static int icnss_driver_event_register_driver(void *data)
if (ret) {
icnss_pr_err("Driver probe failed: %d, state: 0x%lx, probe_cnt: %d\n",
ret, penv->state, probe_cnt);
+ icnss_block_shutdown(false);
goto power_off;
}
+ icnss_block_shutdown(false);
set_bit(ICNSS_DRIVER_PROBED, &penv->state);
return 0;
@@ -2436,9 +2461,14 @@ static int icnss_driver_event_unregister_driver(void *data)
}
set_bit(ICNSS_DRIVER_UNLOADING, &penv->state);
+
+ icnss_block_shutdown(true);
+
if (penv->ops)
penv->ops->remove(&penv->pdev->dev);
+ icnss_block_shutdown(false);
+
clear_bit(ICNSS_DRIVER_UNLOADING, &penv->state);
clear_bit(ICNSS_DRIVER_PROBED, &penv->state);
@@ -2685,6 +2715,13 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb,
if (code != SUBSYS_BEFORE_SHUTDOWN)
return NOTIFY_OK;
+ if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed &&
+ test_bit(ICNSS_BLOCK_SHUTDOWN, &priv->state)) {
+ if (!wait_for_completion_timeout(&priv->unblock_shutdown,
+ PROBE_TIMEOUT))
+ icnss_pr_err("wlan driver probe timeout\n");
+ }
+
if (test_bit(ICNSS_PDR_REGISTERED, &priv->state)) {
set_bit(ICNSS_FW_DOWN, &priv->state);
icnss_ignore_qmi_timeout(true);
@@ -4050,6 +4087,9 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv)
continue;
case ICNSS_MODE_ON:
seq_puts(s, "MODE ON DONE");
+ continue;
+ case ICNSS_BLOCK_SHUTDOWN:
+ seq_puts(s, "BLOCK SHUTDOWN");
}
seq_printf(s, "UNKNOWN-%d", i);
@@ -4721,6 +4761,8 @@ static int icnss_probe(struct platform_device *pdev)
penv = priv;
+ init_completion(&priv->unblock_shutdown);
+
icnss_pr_info("Platform driver probed successfully\n");
return 0;
@@ -4743,6 +4785,8 @@ static int icnss_remove(struct platform_device *pdev)
icnss_debugfs_destroy(penv);
+ complete_all(&penv->unblock_shutdown);
+
icnss_modem_ssr_unregister_notifier(penv);
destroy_ramdump_device(penv->msa0_dump_dev);
diff --git a/drivers/spmi/spmi-pmic-arb-debug.c b/drivers/spmi/spmi-pmic-arb-debug.c
index 2c90bef1224f..48fe4e985ff5 100644
--- a/drivers/spmi/spmi-pmic-arb-debug.c
+++ b/drivers/spmi/spmi-pmic-arb-debug.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019, 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
@@ -365,17 +365,7 @@ static struct platform_driver spmi_pmic_arb_debug_driver = {
},
};
-int __init spmi_pmic_arb_debug_init(void)
-{
- return platform_driver_register(&spmi_pmic_arb_debug_driver);
-}
-arch_initcall(spmi_pmic_arb_debug_init);
-
-static void __exit spmi_pmic_arb_debug_exit(void)
-{
- platform_driver_unregister(&spmi_pmic_arb_debug_driver);
-}
-module_exit(spmi_pmic_arb_debug_exit);
+module_platform_driver(spmi_pmic_arb_debug_driver);
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:spmi_pmic_arb_debug");
diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.c b/drivers/video/fbdev/msm/mdp3_ctrl.c
index ff7d7126df85..1f588a3aca20 100644
--- a/drivers/video/fbdev/msm/mdp3_ctrl.c
+++ b/drivers/video/fbdev/msm/mdp3_ctrl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, 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
@@ -261,7 +261,8 @@ static void mdp3_vsync_retire_handle_vsync(void *arg)
return;
}
- schedule_work(&mdp3_session->retire_work);
+ kthread_queue_work(&mdp3_session->retire_worker,
+ &mdp3_session->retire_work);
}
void mdp3_vsync_retire_signal(struct msm_fb_data_type *mfd, int val)
@@ -282,7 +283,7 @@ void mdp3_vsync_retire_signal(struct msm_fb_data_type *mfd, int val)
mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex);
}
-static void mdp3_vsync_retire_work_handler(struct work_struct *work)
+static void mdp3_vsync_retire_work_handler(struct kthread_work *work)
{
struct mdp3_session_data *mdp3_session =
container_of(work, struct mdp3_session_data, retire_work);
@@ -2981,6 +2982,7 @@ static int mdp3_vsync_retire_setup(struct msm_fb_data_type *mfd)
struct mdp3_session_data *mdp3_session;
struct mdp3_notification retire_client;
char name[24];
+ struct sched_param param = { .sched_priority = 16 };
mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
@@ -2998,7 +3000,20 @@ static int mdp3_vsync_retire_setup(struct msm_fb_data_type *mfd)
if (mdp3_session->dma)
mdp3_session->dma->retire_client = retire_client;
- INIT_WORK(&mdp3_session->retire_work, mdp3_vsync_retire_work_handler);
+ kthread_init_worker(&mdp3_session->retire_worker);
+ kthread_init_work(&mdp3_session->retire_work,
+ mdp3_vsync_retire_work_handler);
+
+ mdp3_session->retire_thread = kthread_run(kthread_worker_fn,
+ &mdp3_session->retire_worker,
+ "vsync_retire_work");
+ if (IS_ERR(mdp3_session->retire_thread)) {
+ pr_err("unable to start vsync thread\n");
+ mdp3_session->retire_thread = NULL;
+ return -ENOMEM;
+ }
+
+ sched_setscheduler(mdp3_session->retire_thread, SCHED_FIFO, &param);
return 0;
}
diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.h b/drivers/video/fbdev/msm/mdp3_ctrl.h
index 032debe1aa85..07377a92981e 100644
--- a/drivers/video/fbdev/msm/mdp3_ctrl.h
+++ b/drivers/video/fbdev/msm/mdp3_ctrl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 2016-2019, 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
@@ -61,6 +61,10 @@ struct mdp3_session_data {
struct kthread_worker worker;
struct task_struct *thread;
+ struct kthread_work retire_work;
+ struct kthread_worker retire_worker;
+ struct task_struct *retire_thread;
+
atomic_t dma_done_cnt;
int histo_status;
struct mutex histo_lock;
@@ -84,7 +88,6 @@ struct mdp3_session_data {
/* For retire fence */
struct mdss_timeline *vsync_timeline;
int retire_cnt;
- struct work_struct retire_work;
};
void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq, int client);
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index e69ebe648a34..be3e1db832b5 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -456,17 +456,12 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
return inode;
}
-int proc_fill_super(struct super_block *s, void *data, int silent)
+int proc_fill_super(struct super_block *s)
{
- struct pid_namespace *ns = get_pid_ns(s->s_fs_info);
struct inode *root_inode;
int ret;
- if (!proc_parse_options(data, ns))
- return -EINVAL;
-
- /* User space would break if executables or devices appear on proc */
- s->s_iflags |= SB_I_USERNS_VISIBLE | SB_I_NOEXEC | SB_I_NODEV;
+ s->s_iflags |= SB_I_USERNS_VISIBLE | SB_I_NODEV;
s->s_flags |= MS_NODIRATIME | MS_NOSUID | MS_NOEXEC;
s->s_blocksize = 1024;
s->s_blocksize_bits = 10;
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index d8105cd8b01c..d8edf39e0c1d 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -213,7 +213,7 @@ extern const struct file_operations proc_reclaim_operations;
extern void proc_init_inodecache(void);
extern struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *);
-extern int proc_fill_super(struct super_block *, void *data, int flags);
+extern int proc_fill_super(struct super_block *);
extern void proc_entry_rundown(struct proc_dir_entry *);
/*
@@ -278,7 +278,6 @@ static inline void proc_tty_init(void) {}
* root.c
*/
extern struct proc_dir_entry proc_root;
-extern int proc_parse_options(char *options, struct pid_namespace *pid);
extern void proc_self_init(void);
extern int proc_remount(struct super_block *, int *, char *);
diff --git a/fs/proc/root.c b/fs/proc/root.c
index c2f5014d642d..1d68fcd9313f 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -23,6 +23,21 @@
#include "internal.h"
+static int proc_test_super(struct super_block *sb, void *data)
+{
+ return sb->s_fs_info == data;
+}
+
+static int proc_set_super(struct super_block *sb, void *data)
+{
+ int err = set_anon_super(sb, NULL);
+ if (!err) {
+ struct pid_namespace *ns = (struct pid_namespace *)data;
+ sb->s_fs_info = get_pid_ns(ns);
+ }
+ return err;
+}
+
enum {
Opt_gid, Opt_hidepid, Opt_err,
};
@@ -33,7 +48,7 @@ static const match_table_t tokens = {
{Opt_err, NULL},
};
-int proc_parse_options(char *options, struct pid_namespace *pid)
+static int proc_parse_options(char *options, struct pid_namespace *pid)
{
char *p;
substring_t args[MAX_OPT_ARGS];
@@ -85,16 +100,45 @@ int proc_remount(struct super_block *sb, int *flags, char *data)
static struct dentry *proc_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
+ int err;
+ struct super_block *sb;
struct pid_namespace *ns;
+ char *options;
if (flags & MS_KERNMOUNT) {
- ns = data;
- data = NULL;
+ ns = (struct pid_namespace *)data;
+ options = NULL;
} else {
ns = task_active_pid_ns(current);
+ options = data;
+
+ /* Does the mounter have privilege over the pid namespace? */
+ if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN))
+ return ERR_PTR(-EPERM);
+ }
+
+ sb = sget(fs_type, proc_test_super, proc_set_super, flags, ns);
+ if (IS_ERR(sb))
+ return ERR_CAST(sb);
+
+ if (!proc_parse_options(options, ns)) {
+ deactivate_locked_super(sb);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!sb->s_root) {
+ err = proc_fill_super(sb);
+ if (err) {
+ deactivate_locked_super(sb);
+ return ERR_PTR(err);
+ }
+
+ sb->s_flags |= MS_ACTIVE;
+ /* User space would break if executables appear on proc */
+ sb->s_iflags |= SB_I_NOEXEC;
}
- return mount_ns(fs_type, flags, data, ns, ns->user_ns, proc_fill_super);
+ return dget(sb->s_root);
}
static void proc_kill_sb(struct super_block *sb)
diff --git a/include/linux/hdcp_qseecom.h b/include/linux/hdcp_qseecom.h
index 08f30a46726f..9d13f24a33d4 100644
--- a/include/linux/hdcp_qseecom.h
+++ b/include/linux/hdcp_qseecom.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, 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
@@ -215,6 +215,7 @@ struct hdcp_register_data {
int hdcp_library_register(struct hdcp_register_data *data);
void hdcp_library_deregister(void *phdcpcontext);
bool hdcp1_check_if_supported_load_app(void);
+void hdcp1_unload_app(void);
int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb);
int hdcp1_set_enc(bool enable);
#endif /* __HDCP_QSEECOM_H */
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index d32e7b8c0b87..29dedd4eb1b1 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -497,8 +497,8 @@ struct perf_addr_filters_head {
* enum perf_event_active_state - the states of a event
*/
enum perf_event_active_state {
- PERF_EVENT_STATE_DEAD = -5,
- PERF_EVENT_STATE_ZOMBIE = -4,
+ PERF_EVENT_STATE_DORMANT = -5,
+ PERF_EVENT_STATE_DEAD = -4,
PERF_EVENT_STATE_EXIT = -3,
PERF_EVENT_STATE_ERROR = -2,
PERF_EVENT_STATE_OFF = -1,
@@ -721,7 +721,13 @@ struct perf_event {
/* Is this event shared with other events */
bool shared;
- struct list_head zombie_entry;
+
+ /*
+ * Entry into the list that holds the events whose CPUs
+ * are offline. These events will be installed once the
+ * CPU wakes up and will be removed from the list after that
+ */
+ struct list_head dormant_event_entry;
#endif /* CONFIG_PERF_EVENTS */
};
@@ -1401,9 +1407,11 @@ static struct device_attribute format_attr_##_name = __ATTR_RO(_name)
#ifdef CONFIG_PERF_EVENTS
int perf_event_init_cpu(unsigned int cpu);
int perf_event_exit_cpu(unsigned int cpu);
+int perf_event_restart_events(unsigned int cpu);
#else
#define perf_event_init_cpu NULL
#define perf_event_exit_cpu NULL
+#define perf_event_restart_events NULL
#endif
#endif /* _LINUX_PERF_EVENT_H */
diff --git a/include/soc/qcom/icnss.h b/include/soc/qcom/icnss.h
index 7ef3db418100..0732a6fd33d1 100644
--- a/include/soc/qcom/icnss.h
+++ b/include/soc/qcom/icnss.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, 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
@@ -144,4 +144,5 @@ extern bool icnss_is_fw_ready(void);
extern bool icnss_is_fw_down(void);
extern bool icnss_is_rejuvenate(void);
extern int icnss_trigger_recovery(struct device *dev);
+extern void icnss_block_shutdown(bool status);
#endif /* _ICNSS_WLAN_H_ */
diff --git a/include/uapi/media/cam_defs.h b/include/uapi/media/cam_defs.h
index db433542860b..e69fe7ab5f96 100644
--- a/include/uapi/media/cam_defs.h
+++ b/include/uapi/media/cam_defs.h
@@ -163,7 +163,8 @@ struct cam_iommu_handle {
#define CAM_FORMAT_PLAIN8_10_SWAP 43
#define CAM_FORMAT_YV12 44
#define CAM_FORMAT_Y_ONLY 45
-#define CAM_FORMAT_MAX 46
+#define CAM_FORMAT_DPCM_12_10_12 46
+#define CAM_FORMAT_MAX 47
/* camera rotaion */
#define CAM_ROTATE_CW_0_DEGREE 0
diff --git a/include/uapi/media/cam_isp.h b/include/uapi/media/cam_isp.h
index 2344b223ec0d..91360e240b49 100644
--- a/include/uapi/media/cam_isp.h
+++ b/include/uapi/media/cam_isp.h
@@ -89,6 +89,7 @@
#define CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG 2
#define CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG 3
#define CAM_ISP_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG 4
+#define CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG 5
/* Query devices */
/**
@@ -386,6 +387,44 @@ struct cam_isp_bw_config {
struct cam_isp_bw_vote rdi_vote[1];
} __attribute__((packed));
+/**
+ * struct cam_fe_config - Fetch Engine configuration
+ *
+ * @version: fetch engine veriosn
+ * @min_vbi: require min vbi
+ * @fs_mode: indicates if fs mode enabled
+ * @fs_line_sync_en: frame level sync or line level
+ * sync for fetch engine
+ * @hbi_count: hbi count
+ * @fs_sync_enable: indicates if fetch engine working
+ * wokring in sync with write engine
+ * @go_cmd_sel: softwrae go_cmd or hw go_cmd
+ * @client_enable: enable read engine
+ * @source_addr: adrress of buffer to read from
+ * @width: buffer width
+ * @height: buffer height
+ * @stride: buffer stride (here equal to width)
+ * @format: format of image in buffer
+ * @unpacker_cfg: unpacker config type
+ * @latency_buf_size: latency buffer for read engine
+ */
+struct cam_fe_config {
+ uint64_t version;
+ uint32_t min_vbi;
+ uint32_t fs_mode;
+ uint32_t fs_line_sync_en;
+ uint32_t hbi_count;
+ uint32_t fs_sync_enable;
+ uint32_t go_cmd_sel;
+ uint32_t client_enable;
+ uint32_t source_addr;
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
+ uint32_t format;
+ uint32_t unpacker_cfg;
+ uint32_t latency_buf_size;
+} __attribute__((packed));
/* Acquire Device/HW v2 */
diff --git a/include/uapi/media/cam_isp_ife.h b/include/uapi/media/cam_isp_ife.h
index b806befa2bed..7e9ba62c507f 100644
--- a/include/uapi/media/cam_isp_ife.h
+++ b/include/uapi/media/cam_isp_ife.h
@@ -27,7 +27,8 @@
#define CAM_ISP_IFE_OUT_RES_DS4_DISP (CAM_ISP_IFE_OUT_RES_BASE + 20)
#define CAM_ISP_IFE_OUT_RES_DS16_DISP (CAM_ISP_IFE_OUT_RES_BASE + 21)
#define CAM_ISP_IFE_OUT_RES_2PD (CAM_ISP_IFE_OUT_RES_BASE + 22)
-#define CAM_ISP_IFE_OUT_RES_MAX (CAM_ISP_IFE_OUT_RES_BASE + 23)
+#define CAM_ISP_IFE_OUT_RES_RDI_RD (CAM_ISP_IFE_OUT_RES_BASE + 23)
+#define CAM_ISP_IFE_OUT_RES_MAX (CAM_ISP_IFE_OUT_RES_BASE + 24)
/*IFE input port resource type (global unique) */
#define CAM_ISP_IFE_IN_RES_BASE 0x4000
@@ -37,6 +38,7 @@
#define CAM_ISP_IFE_IN_RES_PHY_1 (CAM_ISP_IFE_IN_RES_BASE + 2)
#define CAM_ISP_IFE_IN_RES_PHY_2 (CAM_ISP_IFE_IN_RES_BASE + 3)
#define CAM_ISP_IFE_IN_RES_PHY_3 (CAM_ISP_IFE_IN_RES_BASE + 4)
-#define CAM_ISP_IFE_IN_RES_MAX (CAM_ISP_IFE_IN_RES_BASE + 5)
+#define CAM_ISP_IFE_IN_RES_RD (CAM_ISP_IFE_IN_RES_BASE + 5)
+#define CAM_ISP_IFE_IN_RES_MAX (CAM_ISP_IFE_IN_RES_BASE + 6)
#endif /* __UAPI_CAM_ISP_IFE_H__ */
diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h
index 0b4f1cc40df3..b903078dccbd 100644
--- a/include/uapi/media/cam_req_mgr.h
+++ b/include/uapi/media/cam_req_mgr.h
@@ -383,10 +383,12 @@ struct cam_mem_cache_ops_cmd {
* @CAM_REQ_MGR_ERROR_TYPE_DEVICE: Device error message, fatal to session
* @CAM_REQ_MGR_ERROR_TYPE_REQUEST: Error on a single request, not fatal
* @CAM_REQ_MGR_ERROR_TYPE_BUFFER: Buffer was not filled, not fatal
+ * @CAM_REQ_MGR_ERROR_TYPE_RECOVERY: Fatal error, can be recovered
*/
#define CAM_REQ_MGR_ERROR_TYPE_DEVICE 0
#define CAM_REQ_MGR_ERROR_TYPE_REQUEST 1
#define CAM_REQ_MGR_ERROR_TYPE_BUFFER 2
+#define CAM_REQ_MGR_ERROR_TYPE_RECOVERY 3
/**
* struct cam_req_mgr_error_msg
diff --git a/kernel/cpu.c b/kernel/cpu.c
index aa035154bb72..df007c474778 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -1463,7 +1463,7 @@ static struct cpuhp_step cpuhp_ap_states[] = {
},
[CPUHP_AP_PERF_ONLINE] = {
.name = "perf:online",
- .startup.single = perf_event_init_cpu,
+ .startup.single = perf_event_restart_events,
.teardown.single = perf_event_exit_cpu,
},
[CPUHP_AP_WORKQUEUE_ONLINE] = {
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 6be8ea2fb116..8dd675001654 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -2315,6 +2315,23 @@ static void ctx_resched(struct perf_cpu_context *cpuctx,
perf_pmu_enable(cpuctx->ctx.pmu);
}
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+static LIST_HEAD(dormant_event_list);
+static DEFINE_SPINLOCK(dormant_event_list_lock);
+
+static void perf_prepare_install_in_context(struct perf_event *event)
+{
+ spin_lock(&dormant_event_list_lock);
+ if (event->state == PERF_EVENT_STATE_DORMANT)
+ goto out;
+
+ event->state = PERF_EVENT_STATE_DORMANT;
+ list_add_tail(&event->dormant_event_entry, &dormant_event_list);
+out:
+ spin_unlock(&dormant_event_list_lock);
+}
+#endif
+
/*
* Cross CPU call to install and enable a performance event
*
@@ -2460,6 +2477,34 @@ again:
raw_spin_unlock_irq(&ctx->lock);
}
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+static void perf_deferred_install_in_context(int cpu)
+{
+ struct perf_event *event, *tmp;
+ struct perf_event_context *ctx;
+
+ spin_lock(&dormant_event_list_lock);
+ list_for_each_entry_safe(event, tmp, &dormant_event_list,
+ dormant_event_entry) {
+ if (cpu != event->cpu)
+ continue;
+
+ list_del(&event->dormant_event_entry);
+ event->state = PERF_EVENT_STATE_INACTIVE;
+ spin_unlock(&dormant_event_list_lock);
+
+ ctx = event->ctx;
+
+ mutex_lock(&ctx->mutex);
+ perf_install_in_context(ctx, event, cpu);
+ mutex_unlock(&ctx->mutex);
+
+ spin_lock(&dormant_event_list_lock);
+ }
+ spin_unlock(&dormant_event_list_lock);
+}
+#endif
+
/*
* Put a event into inactive state and update time fields.
* Enabling the leader of a group effectively enables all
@@ -4277,14 +4322,6 @@ static void put_event(struct perf_event *event)
}
/*
- * Maintain a zombie list to collect all the zombie events
- */
-#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
-static LIST_HEAD(zombie_list);
-static DEFINE_SPINLOCK(zombie_list_lock);
-#endif
-
-/*
* Kill an event dead; while event:refcount will preserve the event
* object, it will not preserve its functionality. Once the last 'user'
* gives up the object, we'll destroy the thing.
@@ -4294,23 +4331,12 @@ static int __perf_event_release_kernel(struct perf_event *event)
struct perf_event_context *ctx = event->ctx;
struct perf_event *child, *tmp;
- /*
- * If the cpu associated to this event is offline, set the event as a
- * zombie event. The cleanup of the cpu would be done if the CPU is
- * back online.
- */
#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
- if (event->cpu != -1 && per_cpu(is_hotplugging, event->cpu)) {
- if (event->state == PERF_EVENT_STATE_ZOMBIE)
- return 0;
-
- event->state = PERF_EVENT_STATE_ZOMBIE;
-
- spin_lock(&zombie_list_lock);
- list_add_tail(&event->zombie_entry, &zombie_list);
- spin_unlock(&zombie_list_lock);
-
- return 0;
+ if (event->cpu != -1) {
+ spin_lock(&dormant_event_list_lock);
+ if (event->state == PERF_EVENT_STATE_DORMANT)
+ list_del(&event->dormant_event_entry);
+ spin_unlock(&dormant_event_list_lock);
}
#endif
@@ -4627,6 +4653,15 @@ perf_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
struct perf_event_context *ctx;
int ret;
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+ spin_lock(&dormant_event_list_lock);
+ if (event->state == PERF_EVENT_STATE_DORMANT) {
+ spin_unlock(&dormant_event_list_lock);
+ return 0;
+ }
+ spin_unlock(&dormant_event_list_lock);
+#endif
+
ctx = perf_event_ctx_lock(event);
ret = __perf_read(event, buf, count);
perf_event_ctx_unlock(event, ctx);
@@ -9455,13 +9490,13 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
mutex_init(&event->child_mutex);
INIT_LIST_HEAD(&event->child_list);
+ INIT_LIST_HEAD(&event->dormant_event_entry);
INIT_LIST_HEAD(&event->group_entry);
INIT_LIST_HEAD(&event->event_entry);
INIT_LIST_HEAD(&event->sibling_list);
INIT_LIST_HEAD(&event->rb_entry);
INIT_LIST_HEAD(&event->active_entry);
INIT_LIST_HEAD(&event->addr_filters.list);
- INIT_LIST_HEAD(&event->zombie_entry);
INIT_HLIST_NODE(&event->hlist_entry);
@@ -11114,111 +11149,27 @@ int perf_event_init_cpu(unsigned int cpu)
}
#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
-static void
-check_hotplug_start_event(struct perf_event *event)
-{
- if (event->pmu->events_across_hotplug &&
- event->attr.type == PERF_TYPE_SOFTWARE &&
- event->pmu->start)
- event->pmu->start(event, 0);
-}
-
-static void perf_event_zombie_cleanup(unsigned int cpu)
+int perf_event_restart_events(unsigned int cpu)
{
- struct perf_event *event, *tmp;
-
- spin_lock(&zombie_list_lock);
-
- list_for_each_entry_safe(event, tmp, &zombie_list, zombie_entry) {
- if (event->cpu != cpu)
- continue;
-
- list_del(&event->zombie_entry);
- spin_unlock(&zombie_list_lock);
-
- /*
- * The detachment of the event with the
- * PMU expects it to be in an active state
- */
- event->state = PERF_EVENT_STATE_ACTIVE;
- __perf_event_release_kernel(event);
-
- spin_lock(&zombie_list_lock);
- }
-
- spin_unlock(&zombie_list_lock);
-}
-
-static int perf_event_start_swevents(unsigned int cpu)
-{
- struct perf_event_context *ctx;
- struct pmu *pmu;
- struct perf_event *event;
- int idx;
-
mutex_lock(&pmus_lock);
- perf_event_zombie_cleanup(cpu);
-
- idx = srcu_read_lock(&pmus_srcu);
- list_for_each_entry_rcu(pmu, &pmus, entry) {
- ctx = &per_cpu_ptr(pmu->pmu_cpu_context, cpu)->ctx;
- mutex_lock(&ctx->mutex);
- raw_spin_lock(&ctx->lock);
- list_for_each_entry(event, &ctx->event_list, event_entry)
- check_hotplug_start_event(event);
- raw_spin_unlock(&ctx->lock);
- mutex_unlock(&ctx->mutex);
- }
- srcu_read_unlock(&pmus_srcu, idx);
per_cpu(is_hotplugging, cpu) = false;
+ perf_deferred_install_in_context(cpu);
mutex_unlock(&pmus_lock);
return 0;
}
-/*
- * If keeping events across hotplugging is supported, do not
- * remove the event list so event lives beyond CPU hotplug.
- * The context is exited via an fd close path when userspace
- * is done and the target CPU is online. If software clock
- * event is active, then stop hrtimer associated with it.
- * Start the timer when the CPU comes back online.
- */
-static void
-check_hotplug_remove_from_context(struct perf_event *event,
- struct perf_cpu_context *cpuctx,
- struct perf_event_context *ctx)
-{
- if (event->pmu->events_across_hotplug &&
- event->attr.type == PERF_TYPE_SOFTWARE &&
- event->pmu->stop)
- event->pmu->stop(event, PERF_EF_UPDATE);
- else if (!event->pmu->events_across_hotplug)
- __perf_remove_from_context(event, cpuctx,
- ctx, (void *)DETACH_GROUP);
-}
-
-static void __perf_event_exit_context(void *__info)
-{
- struct perf_event_context *ctx = __info;
- struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
- struct perf_event *event;
-
- raw_spin_lock(&ctx->lock);
- list_for_each_entry(event, &ctx->event_list, event_entry)
- check_hotplug_remove_from_context(event, cpuctx, ctx);
- raw_spin_unlock(&ctx->lock);
-}
-
static void perf_event_exit_cpu_context(int cpu)
{
struct perf_cpu_context *cpuctx;
struct perf_event_context *ctx;
unsigned long flags;
+ struct perf_event *event, *event_tmp;
struct pmu *pmu;
int idx;
idx = srcu_read_lock(&pmus_srcu);
+ per_cpu(is_hotplugging, cpu) = true;
list_for_each_entry_rcu(pmu, &pmus, entry) {
cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
ctx = &cpuctx->ctx;
@@ -11233,7 +11184,12 @@ static void perf_event_exit_cpu_context(int cpu)
}
mutex_lock(&ctx->mutex);
- smp_call_function_single(cpu, __perf_event_exit_context, ctx, 1);
+ list_for_each_entry_safe(event, event_tmp, &ctx->event_list,
+ event_entry) {
+ perf_remove_from_context(event, DETACH_GROUP);
+ if (event->pmu->events_across_hotplug)
+ perf_prepare_install_in_context(event);
+ }
mutex_unlock(&ctx->mutex);
}
srcu_read_unlock(&pmus_srcu, idx);
@@ -11246,8 +11202,8 @@ static void perf_event_exit_cpu_context(int cpu) { }
int perf_event_exit_cpu(unsigned int cpu)
{
+
mutex_lock(&pmus_lock);
- per_cpu(is_hotplugging, cpu) = true;
perf_event_exit_cpu_context(cpu);
mutex_unlock(&pmus_lock);
return 0;
@@ -11292,25 +11248,6 @@ static struct notifier_block perf_event_idle_nb = {
.notifier_call = event_idle_notif,
};
-#ifdef CONFIG_HOTPLUG_CPU
-static int perf_cpu_hp_init(void)
-{
- int ret;
-
- ret = cpuhp_setup_state_nocalls(CPUHP_AP_PERF_ONLINE,
- "PERF/CORE/CPUHP_AP_PERF_ONLINE",
- perf_event_start_swevents,
- perf_event_exit_cpu);
- if (ret)
- pr_err("CPU hotplug notifier for perf core could not be registered: %d\n",
- ret);
-
- return ret;
-}
-#else
-static int perf_cpu_hp_init(void) { return 0; }
-#endif
-
void __init perf_event_init(void)
{
int ret, cpu;
@@ -11337,8 +11274,6 @@ void __init perf_event_init(void)
perf_event_init_cpu(smp_processor_id());
idle_notifier_register(&perf_event_idle_nb);
register_reboot_notifier(&perf_reboot_notifier);
- ret = perf_cpu_hp_init();
- WARN(ret, "core perf_cpu_hp_init() failed with: %d", ret);
ret = init_hw_breakpoint();
WARN(ret, "hw_breakpoint initialization failed with: %d", ret);
diff --git a/mm/memory.c b/mm/memory.c
index ccf1a6b9f7e1..b8f1279e3728 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1971,7 +1971,7 @@ int apply_to_page_range(struct mm_struct *mm, unsigned long addr,
unsigned long end = addr + size;
int err;
- if (WARN_ON(addr >= end))
+ if (WARN_ON(addr >= end - 1))
return -EINVAL;
pgd = pgd_offset(mm, addr);
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index 7c1b14868313..8e471bec64c8 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -25,20 +25,20 @@ country AE: DFS-ETSI
country AF: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country AI: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country AL: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -49,8 +49,8 @@ country AM: DFS-ETSI
country AN: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -73,8 +73,8 @@ country AS: DFS-FCC
country AT: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -92,8 +92,8 @@ country AU: DFS-FCC
country AW: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country AZ: DFS-ETSI
@@ -103,8 +103,8 @@ country AZ: DFS-ETSI
country BA: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -120,8 +120,8 @@ country BD:
country BE: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -136,8 +136,8 @@ country BF: DFS-FCC
country BG: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -150,8 +150,8 @@ country BH:
country BL: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country BM: DFS-FCC
@@ -192,14 +192,14 @@ country BS: DFS-FCC
country BT: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country BY: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country BZ:
@@ -226,8 +226,8 @@ country CF: DFS-FCC
country CH: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -280,8 +280,8 @@ country CX: DFS-FCC
country CY: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -291,8 +291,8 @@ country CY: DFS-ETSI
# and http://www.ctu.eu/164/download/VOR/VOR-12-05-2007-6-AN.pdf
country CZ: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -306,8 +306,8 @@ country CZ: DFS-ETSI
country DE: DFS-ETSI
# entries 279004 and 280006
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -315,8 +315,8 @@ country DE: DFS-ETSI
country DK: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -351,8 +351,8 @@ country EC: DFS-FCC
country EE: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -365,8 +365,8 @@ country EG: DFS-ETSI
country ES: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -374,14 +374,14 @@ country ES: DFS-ETSI
country ET: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country FI: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -396,8 +396,8 @@ country FM: DFS-FCC
country FR: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -405,8 +405,8 @@ country FR: DFS-ETSI
country GB: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -426,8 +426,8 @@ country GE: DFS-ETSI
country GF: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -440,26 +440,26 @@ country GH: DFS-FCC
country GI: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country GL: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country GP: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country GR: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -467,8 +467,8 @@ country GR: DFS-ETSI
country GT: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country GU: DFS-FCC
@@ -503,8 +503,8 @@ country HN:
country HR: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -519,8 +519,8 @@ country HT: DFS-FCC
country HU: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -533,8 +533,8 @@ country ID:
country IE: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -547,21 +547,23 @@ country IL: DFS-ETSI
# 60 gHz band channels 1-4, base on Etsi En 302 567
(57000 - 66000 @ 2160), (40)
-country IN:
- (2402 - 2482 @ 40), (20)
- (5170 - 5330 @ 160), (23)
- (5735 - 5835 @ 80), (33)
+country IN: DFS-ETSI
+ (2402 - 2482 @ 40), (30)
+ (5170 - 5250 @ 80), (30), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5875 @ 80), (30)
country IQ: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country IS: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -569,8 +571,8 @@ country IS: DFS-ETSI
country IT: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -593,10 +595,10 @@ country JO:
(57000 - 66000 @ 2160), (40)
country JP: DFS-JP
- (2402 - 2482 @ 40), (20)
+ (2402 - 2482 @ 40), (23)
(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
- (5250 - 5330 @ 80), (26), DFS, AUTO-BW, NO-OUTDOOR
- (5490 - 5710 @ 160), (26), DFS
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
+ (5490 - 5710 @ 160), (23), DFS
# 60 gHz band channels 1-4
(57240 - 65880 @ 2160), (40)
@@ -608,8 +610,8 @@ country KE: DFS-ETSI
country KH: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country KN: DFS-FCC
@@ -660,8 +662,8 @@ country LC: DFS-FCC
country LI: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -676,14 +678,14 @@ country LK: DFS-FCC
country LS: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country LT: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -691,8 +693,8 @@ country LT: DFS-ETSI
country LU: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -700,8 +702,8 @@ country LU: DFS-ETSI
country LV: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -716,29 +718,29 @@ country MA: DFS-ETSI
country MC: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
country MD: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
country ME: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
country MF: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country MH: DFS-FCC
@@ -750,8 +752,8 @@ country MH: DFS-FCC
country MK: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -778,21 +780,21 @@ country MP: DFS-FCC
country MQ: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
country MR: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country MT: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -800,8 +802,8 @@ country MT: DFS-ETSI
country MU: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -813,8 +815,8 @@ country MV: DFS-ETSI
country MW: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country MX: DFS-FCC
@@ -858,8 +860,8 @@ country NI: DFS-FCC
country NL: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -867,8 +869,8 @@ country NL: DFS-ETSI
country NO: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -890,8 +892,8 @@ country NZ: DFS-FCC
country OM: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country PA:
@@ -910,8 +912,8 @@ country PE: DFS-FCC
country PF: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -937,8 +939,8 @@ country PK:
country PL: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -946,8 +948,8 @@ country PL: DFS-ETSI
country PM: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -967,8 +969,8 @@ country PS: DFS-FCC
country PT: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -999,14 +1001,14 @@ country QA: DFS-ETSI
country RE: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country RO: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -1016,8 +1018,8 @@ country RO: DFS-ETSI
# http://www.ratel.rs/upload/documents/Plan_namene/Plan_namene-sl_glasnik.pdf
country RS: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -1047,8 +1049,8 @@ country SA: DFS-ETSI
country SE: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -1065,8 +1067,8 @@ country SG: DFS-FCC
country SI: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -1074,8 +1076,8 @@ country SI: DFS-ETSI
country SK: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -1089,8 +1091,8 @@ country SN:
country SR: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country SV: DFS-FCC
@@ -1108,14 +1110,14 @@ country TC: DFS-FCC
country TD: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country TG: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 40), (23)
- (5250 - 5330 @ 40), (23), DFS
+ (5170 - 5250 @ 40), (23), NO-OUTDOOR
+ (5250 - 5330 @ 40), (23), DFS, NO-OUTDOOR
(5490 - 5710 @ 40), (30), DFS
country TH: DFS-FCC
@@ -1134,8 +1136,8 @@ country TN: DFS-ETSI
country TR: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -1210,8 +1212,8 @@ country UZ: DFS-ETSI
country VC: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -1246,14 +1248,14 @@ country VU: DFS-FCC
country WF: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country WS: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 40), (23)
- (5250 - 5330 @ 40), (23), DFS
+ (5170 - 5250 @ 40), (23), NO-OUTDOOR
+ (5250 - 5330 @ 40), (23), DFS, NO-OUTDOOR
(5490 - 5710 @ 40), (30), DFS
country XA: DFS-JP
@@ -1268,8 +1270,8 @@ country YE:
country YT: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country ZA: DFS-FCC
@@ -1283,6 +1285,6 @@ country ZA: DFS-FCC
country ZW: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS